<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Julia Community 🟣: Johannes Hidding</title>
    <description>The latest articles on Julia Community 🟣 by Johannes Hidding (@jhidding).</description>
    <link>https://forem.julialang.org/jhidding</link>
    <image>
      <url>https://forem.julialang.org/images/7We249WeL2B19hn_jf_w0odcfOjSImP1jXfjFgKHC_w/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L3VzZXIvcHJvZmls/ZV9pbWFnZS84OTcv/MmRhMmI4ZWEtZjYz/MC00NDM1LWJmM2Et/YzQ3MWY0ZWFmMDFk/LmpwZWc</url>
      <title>Julia Community 🟣: Johannes Hidding</title>
      <link>https://forem.julialang.org/jhidding</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.julialang.org/feed/jhidding"/>
    <language>en</language>
    <item>
      <title>Literate programming using Documenter.jl and Entangled</title>
      <dc:creator>Johannes Hidding</dc:creator>
      <pubDate>Sun, 04 Dec 2022 09:46:28 +0000</pubDate>
      <link>https://forem.julialang.org/jhidding/literate-programming-using-documenterjl-and-entangled-3fmb</link>
      <guid>https://forem.julialang.org/jhidding/literate-programming-using-documenterjl-and-entangled-3fmb</guid>
      <description>&lt;p&gt;Here I explain my workflow for literate programming in Julia using &lt;a href="https://documenter.juliadocs.org/stable/"&gt;Documenter.jl&lt;/a&gt; and &lt;a href="https://entangled.github.io"&gt;Entangled&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Literate Programming
&lt;/h2&gt;

&lt;p&gt;Literate programming is a method of programming where you write all your code in a markup document (traditionally LaTeX, but these days Markdown is the obvious choice) in the form of code blocks. The technique has been popularised in a weaker form by the use of notebooks. There are some fundamental problems with the way notebooks are used. &lt;a href="https://youtu.be/7jiPeIFXb6U"&gt;Joel Grus explains this very eloquently: I don't like notebooks.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Real literate programming works with a system of references. This form of literate programming is completely generic over languages, and much more powerful than what you can do with &lt;code&gt;Literate.jl&lt;/code&gt; for instance. You give every code block a name. In Markdown this can be done by annotating code blocks with identifiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;``` {.julia #pythagoras}
sqrt(x^2 + y^2)
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can reference this code block in other blocks as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;``` {.julia #hypothenuse}
hypothenuse(x, y) =
     &amp;lt;&amp;lt;pythagoras&amp;gt;&amp;gt;
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can build a complete program by annotating file output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;``` {.julia file=src/Geometry.jl}
module Geometry
&amp;lt;&amp;lt;hypothenuse&amp;gt;&amp;gt;
end  # module
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This system of references was pioneered by Donald Knuth, and simplified by Norman Ramsey in Noweb.&lt;/p&gt;

&lt;p&gt;I have developed a tool called &lt;a href="https://entangled.github.io/"&gt;Entangled&lt;/a&gt; that helps with writing literate programs. It is a daemon that watches your Markdown files for changes and keeps the tangled source code up-to-date. Even better, if you then change any of the tangled source files, these changes are automatically merged back into your markdown.&lt;/p&gt;

&lt;p&gt;Usually I combine Entangled with &lt;a href="https://pandoc.org/"&gt;Pandoc&lt;/a&gt;, but when the main language is Julia, Entangled also works together really well with &lt;code&gt;Documenter.jl&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Howto combine with &lt;code&gt;Documenter.jl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Traditional documentation in Julia is usualy made using the &lt;code&gt;Documenter&lt;/code&gt; module. This has features for doc-testing and also inline code evaluation that combine well with Entangled. All it needs is a little bit extra scripting to annotate the code blocks in the generated output.&lt;/p&gt;

&lt;p&gt;I use an Awk script to filter the Markdown source files, so that annotations are added where needed. To run this pass before the rest of &lt;code&gt;Documenter.jl&lt;/code&gt; I have customized &lt;code&gt;make.jl&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Since we are celebrating the happy Yule tide of Advent of Code, I have &lt;a href="https://jhidding.github.io/aoc2022/"&gt;my Julia solutions in literate form&lt;/a&gt;. Enjoy!&lt;/p&gt;

</description>
      <category>literateprogramming</category>
      <category>documentation</category>
      <category>tools</category>
    </item>
    <item>
      <title>Computing polynomials: outperforming C++</title>
      <dc:creator>Johannes Hidding</dc:creator>
      <pubDate>Thu, 01 Dec 2022 14:13:37 +0000</pubDate>
      <link>https://forem.julialang.org/jhidding/computing-polynomials-outperforming-c-1i8k</link>
      <guid>https://forem.julialang.org/jhidding/computing-polynomials-outperforming-c-1i8k</guid>
      <description>&lt;p&gt;When you want to convince people that Julia is the best language for some task, some are easily swayed by the beautiful syntax, rank polymorphism, and flirtations with functional programming. In all honesty, those people need little convincing. Others want to see hard numbers!&lt;/p&gt;

&lt;p&gt;Here's a very small demo that shows how Julia can outperform any traditional language: computing polynomials.&lt;/p&gt;

&lt;p&gt;Suppose we have a function described by&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;f(x)=∑cixi,
f(x) = \sum c_i x^i,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where we have the coefficients stored in some dense vector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="nc"&gt; Polynomial&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can evaluate this function as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Polynomial&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;})(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;xpow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;xpow&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
        &lt;span class="n"&gt;xpow&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;xpow&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very much how you would implement such a function in most other languages. In Julia however, we can do something much nicer: generate a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; expand&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Polynomial&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;})&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;::$&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="x"&gt;((&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="o"&gt;*$&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;;&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="x"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we &lt;code&gt;expand(f)&lt;/code&gt;, say we have &lt;code&gt;f = Polynomial(1.0, 0.5, 0.333, 0.25)&lt;/code&gt; the generated function will look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;,)&lt;/span&gt;
      &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
      &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
          &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
          &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
          &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.333&lt;/span&gt;
          &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run this, we say &lt;code&gt;f_unroll = eval(expand(f))&lt;/code&gt;. Not only does this run much faster than our previous loopy implementation, it even outperforms C++ (GCC at &lt;code&gt;-O3&lt;/code&gt;) by more than a factor of two (depending on your machine). The reason is that we have no loop in our generated code, and more importantly, we are not accessing any memory. We have done something that a C++ programmer wouldn't dream of doing: write a code generator, compile the specialised code, and fly to the moon!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jhidding.github.io/MacroExercises.jl/dev/polynomials/#Polynomials"&gt;A completely literate and Documentered implementation of this demo can be found here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit: Thanks to Nicos Pitsianis for point out to me that there is a more efficient method called &lt;a href="https://en.wikipedia.org/wiki/Horner%27s_method"&gt;Horner's method&lt;/a&gt;. This method applies to both Julia and C++ implementations, reducing the amount of multiplications needed. Using this method reduces the difference between Julia and C++ a little bit, but increasing the order of the polynomial grows it back again.&lt;/p&gt;

</description>
      <category>metaprogramming</category>
      <category>demo</category>
    </item>
  </channel>
</rss>
