A trick to have arbitrary infix operators in Python
I can&#x27;t believe I never knew about this.  This is super cool, and although yes it&#x27;s potentially subject to readability problems, it allows you enough freedom to design your desired notation that you might be able to come up with something that&#x27;s <i>more</i> readable than standard Python for a given embedded DSL rather than less, in particular for associative operators.  And it&#x27;s way easier to search the documentation for than non-alphabetic operators.<p>Consider Tk-style page or GUI layout, as in <a href="http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;dev3&#x2F;alglayout.py" rel="nofollow">http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;dev3&#x2F;alglayout.py</a> (in OCaml I used `:` and `..` <a href="http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;dev3&#x2F;alglayout.ml" rel="nofollow">http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;dev3&#x2F;alglayout.ml</a>):<p><pre><code>    pageheader |above| (leftsidebar |beside| vstack(*abstracts)) |above| footer
</code></pre>
My Python version used `|` and `-` and `~`, which I think is super confusing, and I think would probably be a lot better with named infix operators like the above:<p><pre><code>    vr, hr, dhr = [~String(s) for s in &#x27;|-=&#x27;]
    left = ((&#x27;Chapters&#x27; | String(&#x27;&#x27;)) - hr -
            (chapno | vr | [t | ~String(&#x27; . &#x27;) for t in titles]))
    pages = &#x27;Page&#x27; - hr - pnos
    table = ~(&#x27;*&#x27; - hr - &#x27;*&#x27; - &#x27; &#x27;) | &#x27; &#x27; | dhr - (vr | left | pages | vr) - dhr
</code></pre>
This produced this layout:<p><pre><code>    * ========================================================================
    - |Chapters                                                          Page|
    * |----------------------------------------------------------------------|
      | 0.|The unchained desert of the singing perfume. .  .  .  .  .  .    1|
    * | 1.|La brisa ilusa de la neblina abandonada. .  .  .  .  .  .  .    43|
    - | 2.|The smiling murder within her young daughters. .  .  .  .  .    80|
    * | 3.|Aquella hija tortuosa de su precipicio árido. .  .  .  .  .  .  96|
      | 4.|False villages of the foolish monks. .  .  .  .  .  .  .  .  . 114|
    * | 5.|El roble sacrílego de mi sacerdote desmoronado y enlutado. .   124|
    - | 6.|The brazen river of his filthy, fallen ivory. .  .  .  .  .  . 166|
    * | 7.|The laughing monster of his humble scream. .  .  .  .  .  .  . 203|
      | 8.|The rough tattoo of his unchained abomination. .  .  .  .  .   219|
    * | 9.|Los perfumes silenciosos de un árbol monstruoso muriéndose. .  237|
    - |10.|The sweet tower of the smooth fire. .  .  .  .  .  .  .  .  .  247|
    * ========================================================================
</code></pre>
Such named infix operators would also take care of the coercions; instead of writing `(&#x27;Chapters&#x27; | String(&#x27;&#x27;))` I could write `&#x27;Chapters&#x27; |beside| &#x27;&#x27;` and let `beside` do the coercion.†<p>— ⁂ —<p>Another application for weird infix operators is computation on a lattice (in the partial-order sense):<p><pre><code>    w |meet| x |meet| (y |join| z)
</code></pre>
Boolean bitvectors are a lattice, so it might be forgivable to overload the bitwise operators for general lattice elements, but I would argue that the following notation is less readable than the above:<p><pre><code>    w &amp; x &amp; (y | z)
</code></pre>
— ⁂ —<p>How about binary relations, as in <a href="http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;binary-relations" rel="nofollow">http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;binary-relations</a>?<p><pre><code>    neighbor = (x |compose| near |compose| x.T) |union| (y |compose| near |compose| y.T)
</code></pre>
You could usefully apply this to composing SQL queries, for example.  Instead of writing<p><pre><code>    &quot;&quot;&quot;SELECT clients.name, orders.id
    FROM clients, orders
    WHERE clients.id = orders.clientid
    ORDER BY clients.name
    &quot;&quot;&quot;
</code></pre>
you could reasonably write<p><pre><code>    clients.name |product|
     (clients.id |compose| orders.clientid.T
      |compose| orders.id)
</code></pre>
or, with better namespace management, maybe just<p><pre><code>    name |product|
      (clients.id |compose| clientid.T |compose| orders.id)
</code></pre>
— ⁂ —<p>Maybe 3-D modeling, as in <a href="https:&#x2F;&#x2F;dercuano.github.io&#x2F;notes&#x2F;algebraic-graphics.html" rel="nofollow">https:&#x2F;&#x2F;dercuano.github.io&#x2F;notes&#x2F;algebraic-graphics.html</a>?  Extrusion along a path is associative even if it contains rotation, right?<p><pre><code>    square = xline |extrudedby| yline
    cube = square |extrudedby| zline
    twistedcube = square |extrudedby| (zline |during| zrotate(2*math.PI))
</code></pre>
— ⁂ —<p>Maybe melodies, as in <a href="http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;synthgramelodia" rel="nofollow">http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;synthgramelodia</a> and <a href="http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;aspmisc&#x2F;gramelodia.py" rel="nofollow">http:&#x2F;&#x2F;canonical.org&#x2F;~kragen&#x2F;sw&#x2F;aspmisc&#x2F;gramelodia.py</a>?  The operators defined there aren&#x27;t associative but they could be.<p><pre><code>    theme = bell.twice |then| bell.fifthlower |then| rest
    tune = theme.twice.octavehigher |during| theme.slower
    rhythm = boom |then| whack |then| boom.twice.faster |then| whack
    play(rhythm.repeatedly |during| tune)
</code></pre>
Of course the real test is not whether you can write code to say what it means straightforwardly; that&#x27;s necessary but not sufficient.  The real test is whether you get reasonable error messages when you write something like<p><pre><code>    play(rhythm.repeatedly |during| then| tune)
</code></pre>
____<p>† In that particular case, if the code had a purpose other than being an experiment in ultra-minimalism, `ljust(&#x27;Chapters&#x27;)` would have been better: the particular goofy thing I was doing was that string boxes right-justify their strings if they get allocated more space than they need, while horizontal concatenation boxes allocate any extra space they receive to their rightmost box, so you can get left-justified strings by just stacking an empty string box to their right.