Readability: Difference between revisions

Jump to navigation Jump to search
333 bytes added ,  22:28, 10 September 2022
m
Text replacement - "</source>" to "</syntaxhighlight>"
m (Text replacement - "<source" to "<syntaxhighlight")
m (Text replacement - "</source>" to "</syntaxhighlight>")
 
Line 4: Line 4:
[[Code golf]] often results in pornographic code, as does the practice of cramming a whole algorithm into a single line, forming a [[one-liner]]. When computer memory was very limited, such code golf was often a necessary evil.
[[Code golf]] often results in pornographic code, as does the practice of cramming a whole algorithm into a single line, forming a [[one-liner]]. When computer memory was very limited, such code golf was often a necessary evil.


With the advent of [[dfn]]s, it became possible to define a full function or operator on a single line. Since APL [[comment]]s begin at the comment symbol (<syntaxhighlight lang=apl inline>⍝</source>) and continue until the end of the line, it is impossible to comment a one-liner dfn except outside the source. This, coupled with the inability of a [[wikipedia:debugger|debugger]] to meaningfully trace through a one-liner (unless it is capable of [[primitive]]-by-primitive tracing), constitute hardships for a human reader that attempts to read such code.
With the advent of [[dfn]]s, it became possible to define a full function or operator on a single line. Since APL [[comment]]s begin at the comment symbol (<syntaxhighlight lang=apl inline>⍝</syntaxhighlight>) and continue until the end of the line, it is impossible to comment a one-liner dfn except outside the source. This, coupled with the inability of a [[wikipedia:debugger|debugger]] to meaningfully trace through a one-liner (unless it is capable of [[primitive]]-by-primitive tracing), constitute hardships for a human reader that attempts to read such code.


APL containing user defined names is generally not statically parseable, as the [[name class]], and thus the syntactic role, of such names isn't known until runtime.<ref>[[John Scholes|Scholes, John]]. [https://dfns.dyalog.com/n_kk.htm Kind Koloring of d-fnop named ⍵.] Dfns workspace. [[Dyalog Ltd.]]</ref>
APL containing user defined names is generally not statically parseable, as the [[name class]], and thus the syntactic role, of such names isn't known until runtime.<ref>[[John Scholes|Scholes, John]]. [https://dfns.dyalog.com/n_kk.htm Kind Koloring of d-fnop named ⍵.] Dfns workspace. [[Dyalog Ltd.]]</ref>
Line 13: Line 13:
=== Gilman & Rose ===
=== Gilman & Rose ===
In [[Books#APL_.E2.80.95_An_Interactive_Approach|APL ― An Interactive Approach]], the authors describe the following code, which computes the correlation coefficient, as “almost pornographic”:
In [[Books#APL_.E2.80.95_An_Interactive_Approach|APL ― An Interactive Approach]], the authors describe the following code, which computes the correlation coefficient, as “almost pornographic”:
:<syntaxhighlight lang=apl inline>r←(+/x×y)÷((+/(x←x-(+/x)÷⍴x)*2)×+/(y←y-(+/y)÷⍴y)*2)×.5</source>
:<syntaxhighlight lang=apl inline>r←(+/x×y)÷((+/(x←x-(+/x)÷⍴x)*2)×+/(y←y-(+/y)÷⍴y)*2)×.5</syntaxhighlight>
By splitting the expression intro even a moderate number of pieces, a symmetry is revealed:
By splitting the expression intro even a moderate number of pieces, a symmetry is revealed:
<syntaxhighlight lang=apl>yVar←+/(y-(+/y)÷⍴y)*2
<syntaxhighlight lang=apl>yVar←+/(y-(+/y)÷⍴y)*2
xVar←+/(x-(+/x)÷⍴x)*2
xVar←+/(x-(+/x)÷⍴x)*2
r←(+/x×y)÷(xVar×yVar)×0.5</source>
r←(+/x×y)÷(xVar×yVar)×0.5</syntaxhighlight>
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 ([[wikipedia:variance|variance]]). Finally, the <syntaxhighlight lang=apl inline>.5</source> is expanded to <syntaxhighlight lang=apl inline>0.5</source> which helps to clarify that this is a decimal number and not an [[inner product]].
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 ([[wikipedia:variance|variance]]). Finally, the <syntaxhighlight lang=apl inline>.5</syntaxhighlight> is expanded to <syntaxhighlight lang=apl inline>0.5</syntaxhighlight> 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 [[operator]]s 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 [[sum]]mation with [[multiply|multiplication]]
A more modern approach breaks out the symmetry into a utility function [[train]], and uses [[leading axis theory]] combined with [[operator]]s 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 [[sum]]mation with [[multiply|multiplication]]
<syntaxhighlight lang=apl>Var←+/2*⍨⊢-+⌿÷≢
<syntaxhighlight lang=apl>Var←+/2*⍨⊢-+⌿÷≢
R←2×+.×÷×⍥Var
R←2×+.×÷×⍥Var
r←x R y</source>
r←x R y</syntaxhighlight>
Note that <syntaxhighlight lang=apl inline>+⌿÷≢</source> is an [[idiom]] (common phrase) and is read as ''average'' by even moderately experienced APL programmers.
Note that <syntaxhighlight lang=apl inline>+⌿÷≢</syntaxhighlight> is an [[idiom]] (common phrase) and is read as ''average'' by even moderately experienced APL programmers.


=== IBM ===
=== IBM ===
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], Assignment Algorithms. IBM.</ref>
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], Assignment Algorithms. IBM.</ref>
:{| style=width:100%
:{| style=width:100%
|<syntaxhighlight lang=apl inline>X←'line1',0⍴Y←'line2'</source>||<syntaxhighlight lang=apl inline>⍝ Pornography. Combining two lines into one.</source>
|<syntaxhighlight lang=apl inline>X←'line1',0⍴Y←'line2'</syntaxhighlight>||<syntaxhighlight lang=apl inline>⍝ Pornography. Combining two lines into one.</syntaxhighlight>
|}
|}
This was once a common technique before, even though it is prone to fail in where the value to the left of <syntaxhighlight lang=apl inline>,0⍴</source> isn't a vector, for example in the following example where <syntaxhighlight lang=apl inline>X</source> becomes a 1-element [[vector]] instead of the intended [[scalar]]:
This was once a common technique before, even though it is prone to fail in where the value to the left of <syntaxhighlight lang=apl inline>,0⍴</syntaxhighlight> isn't a vector, for example in the following example where <syntaxhighlight lang=apl inline>X</syntaxhighlight> becomes a 1-element [[vector]] instead of the intended [[scalar]]:
<syntaxhighlight lang=apl>
<syntaxhighlight lang=apl>
       X←'l',0⍴Y←'line2'
       X←'l',0⍴Y←'line2'
Line 40: Line 40:
0
0
0
0
</source>
</syntaxhighlight>
With the addition of [[Left]] (<syntaxhighlight lang=apl inline>⊣</source>) to the language, this type of hack became became entirely obsolete:
With the addition of [[Left]] (<syntaxhighlight lang=apl inline>⊣</syntaxhighlight>) to the language, this type of hack became became entirely obsolete:
:<syntaxhighlight lang=apl inline>X←'line1' ⊣ Y←'line2'</source>
:<syntaxhighlight lang=apl inline>X←'line1' ⊣ Y←'line2'</syntaxhighlight>
The primitive leaves its left argument unmodified:
The primitive leaves its left argument unmodified:
<syntaxhighlight lang=apl>
<syntaxhighlight lang=apl>
Line 48: Line 48:
       Y∘.=X
       Y∘.=X
1 0 0 0 0
1 0 0 0 0
</source>
</syntaxhighlight>
The Diamond [[statement separator]] (<syntaxhighlight lang=apl inline>⋄</source>) provides an alternative means of inlining multiple statements:
The Diamond [[statement separator]] (<syntaxhighlight lang=apl inline>⋄</syntaxhighlight>) provides an alternative means of inlining multiple statements:
:<syntaxhighlight lang=apl inline>Y←'line2' ⋄ X←'line1'</source>
:<syntaxhighlight lang=apl inline>Y←'line2' ⋄ X←'line1'</syntaxhighlight>
Note that in all the above, <syntaxhighlight lang=apl inline>Y</source> is assigned first.
Note that in all the above, <syntaxhighlight lang=apl inline>Y</syntaxhighlight> is assigned first.


=== Morten Kromberg ===
=== Morten Kromberg ===
Line 57: Line 57:
:<syntaxhighlight lang=apl inline>
:<syntaxhighlight lang=apl inline>
ns(⍎container.⎕NS)←⍬
ns(⍎container.⎕NS)←⍬
</source>
</syntaxhighlight>
Avoiding the unusual [[modified assignment]] (using the 2-[[train]] <syntaxhighlight lang=apl inline>⍎⎕NS</source> as modifying function) helps:
Avoiding the unusual [[modified assignment]] (using the 2-[[train]] <syntaxhighlight lang=apl inline>⍎⎕NS</syntaxhighlight> as modifying function) helps:
:<syntaxhighlight lang=apl inline>
:<syntaxhighlight lang=apl inline>
ns←ns container.(⍎⎕NS) ⍬
ns←ns container.(⍎⎕NS) ⍬
</source>
</syntaxhighlight>
Finally, splitting the 2-train apart makes it even clearer:
Finally, splitting the 2-train apart makes it even clearer:
:<syntaxhighlight lang=apl inline>
:<syntaxhighlight lang=apl inline>
ns←⍎ns container.⎕NS ⍬
ns←⍎ns container.⎕NS ⍬
</source>
</syntaxhighlight>
A new [[namespace]], with the original value of <syntaxhighlight lang=apl inline>ns</source> as name, is created inside <syntaxhighlight lang=apl inline>container</source> and the character representation <syntaxhighlight lang=apl inline>'#.container.ns'</source> is returned from <syntaxhighlight lang=apl inline>⎕NS</source> to <syntaxhighlight lang=apl inline>⍎</source> which evaluates the name to a reference, that in turn replaces the previous value of <syntaxhighlight lang=apl inline>ns</source>. Note that <syntaxhighlight lang=apl inline>⎕NS</source> returns fully qualified namespace path to the newly created namespace, and thus it doesn't matter in which namespace <syntaxhighlight lang=apl inline>⍎</source> is called.
A new [[namespace]], with the original value of <syntaxhighlight lang=apl inline>ns</syntaxhighlight> as name, is created inside <syntaxhighlight lang=apl inline>container</syntaxhighlight> and the character representation <syntaxhighlight lang=apl inline>'#.container.ns'</syntaxhighlight> is returned from <syntaxhighlight lang=apl inline>⎕NS</syntaxhighlight> to <syntaxhighlight lang=apl inline>⍎</syntaxhighlight> which evaluates the name to a reference, that in turn replaces the previous value of <syntaxhighlight lang=apl inline>ns</syntaxhighlight>. Note that <syntaxhighlight lang=apl inline>⎕NS</syntaxhighlight> returns fully qualified namespace path to the newly created namespace, and thus it doesn't matter in which namespace <syntaxhighlight lang=apl inline>⍎</syntaxhighlight> is called.
=== Honeywell ===
=== Honeywell ===
[[Honeywell]] <ref>Honeywell. [http://www.softwarepreservation.org/projects/apl/Books/198512_Multics%20APL%20Users%20Guide_AK95-02.pdf#page=106 Multics APL User's Guide] (AK95-02), 3-16. December 1985.</ref> used a more specific definition:
[[Honeywell]] <ref>Honeywell. [http://www.softwarepreservation.org/projects/apl/Books/198512_Multics%20APL%20Users%20Guide_AK95-02.pdf#page=106 Multics APL User's Guide] (AK95-02), 3-16. December 1985.</ref> used a more specific definition:
Line 74: Line 74:
a←4
a←4
(a←3)×a
(a←3)×a
</source>
</syntaxhighlight>
where it is undefined whether the initial value for <syntaxhighlight lang=apl inline>a</source> is used at all in the second line, yielding 12, or whether the second assignment is done before [[times]] gets its right argument, and thus the result is 9.
where it is undefined whether the initial value for <syntaxhighlight lang=apl inline>a</syntaxhighlight> is used at all in the second line, yielding 12, or whether the second assignment is done before [[times]] gets its right argument, and thus the result is 9.


Similarly, in
Similarly, in
Line 81: Line 81:
i←2
i←2
(2 1⍴10 20)[i;i←1]
(2 1⍴10 20)[i;i←1]
</source>
</syntaxhighlight>
the evaluation order of the statements in the [[bracket indexing]] is undefined. If <syntaxhighlight lang=apl inline>i</source> is evaluated before <syntaxhighlight lang=apl inline>i←1</source> then the result is 20, otherwise it is 10.
the evaluation order of the statements in the [[bracket indexing]] is undefined. If <syntaxhighlight lang=apl inline>i</syntaxhighlight> is evaluated before <syntaxhighlight lang=apl inline>i←1</syntaxhighlight> then the result is 20, otherwise it is 10.


The Multics APL manual goes on to use the terms ''monstrosity'' and ''eyesore'' for code published in an APL newsletter, such as
The Multics APL manual goes on to use the terms ''monstrosity'' and ''eyesore'' for code published in an APL newsletter, such as
:<syntaxhighlight lang=apl inline>Z[B+(C∧X∊D)/⍳⍴X;]+(24p' Y9  X9 ')[(C←(-≠\''''=X)∧A≤⍴D)/A←(D←'⍵⍺')⍳X;]</source>
:<syntaxhighlight lang=apl inline>Z[B+(C∧X∊D)/⍳⍴X;]+(24p' Y9  X9 ')[(C←(-≠\''''=X)∧A≤⍴D)/A←(D←'⍵⍺')⍳X;]</syntaxhighlight>
The manual suggests that this code should be split into the following expressions:
The manual suggests that this code should be split into the following expressions:
<syntaxhighlight lang=apl>
<syntaxhighlight lang=apl>
Line 93: Line 93:
B←(C∧X∊D)/⍳⍴X
B←(C∧X∊D)/⍳⍴X
Z[B;]←(24p' Y9  X9 ')[C/A;]
Z[B;]←(24p' Y9  X9 ')[C/A;]
</source>
</syntaxhighlight>


== See also ==
== See also ==

Navigation menu