<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Tom Almeida</title>
    <subtitle>code, christianity, and attempts at philosophy</subtitle>
    <link rel="self" type="application/atom+xml" href="https://tommoa.me/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://tommoa.me"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2023-04-10T00:00:00+00:00</updated>
    <id>https://tommoa.me/atom.xml</id>
    <entry xml:lang="en">
        <title>2023 April status update</title>
        <published>2023-04-10T00:00:00+00:00</published>
        <updated>2023-04-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/2023-status-update/"/>
        <id>https://tommoa.me/blog/2023-status-update/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/2023-status-update/">&lt;p&gt;I’ve successfully neglected touching or updating this blog for (I think) close to two years now, almost all of which I have spent working full time as a software engineer.
It’s largely been an enjoyable experience, but I think that what I wrote about in &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;work-enjoyment&#x2F;&quot;&gt;“On the enjoyment of work”&lt;&#x2F;a&gt; has largely turned out to be true.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve found that doing a 40-hour job that is effectively just coding has very much dulled my passion for doing anything with code outside of work.
You can see this effect in the slow down of my activity on my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Tommoa&quot;&gt;GitHub account&lt;&#x2F;a&gt;, on the lack of repositories over on &lt;a href=&quot;https:&#x2F;&#x2F;sr.ht&#x2F;~tommoa&quot;&gt;SourceHut&lt;&#x2F;a&gt;, and my lack of blogging about anything, as much of this blog’s content thus far has been coding related.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of having coding as a hobby, a number of other activities have effectively replaced it; singing, cycling and rock climbing (more specifically bouldering).
I currently cycle around 3-4 hours a week, sing three times a week for a total of around 8 hours a week, and boulder probably around 10 hours a week.
These generally function as nice hobbies to have, that generally work my brain to some extent as well (with the arguable exception of cycling), and all improve parts of my health and well-being in various respects.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Since the last time I wrote a post, I’ve also entirely moved cities!&lt;&#x2F;p&gt;
&lt;p&gt;I moved from Perth (my hometown, though not where I was born), to Sydney.
My work is based in Sydney, so although it was difficult to leave my family behind it made sense to move - especially with Sydney being a state with day-light savings, which always did my head in when I was in Perth as we did not have day light savings.&lt;&#x2F;p&gt;
&lt;p&gt;I was originally planning to move a few years ago once I got my job, but, as with many other things, the COVID-19 pandemic effectively put a stop to it for two years.
It was a relief to finally move and put an end to the limbo-type situation that had occurred whilst I was in Perth, and although Sydney has only been my home for a few months it has certainly started to feel like home.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;A few months ago I started on a project to create a cross-platform podcasting application.
I made it all the way through to being able to go through feeds, download and play individual episodes before very much slowing down development.
For the most part working on this has been good fun - although as noted above I don’t tend to code in my spare time very much anymore, which is of course quite limiting in terms of what I’m able to do.
My main motivation was to have a cross-platform RSS&#x2F;Atom reader and podcast player that I could keep synced and use between all of my devices.
Due to my move to Sydney and thinning down of usable devices some of the motivation for this issue has been assuaged, however I think it may still be something useful to have around as an open source project.&lt;&#x2F;p&gt;
&lt;p&gt;An interesting project that is on a similar trajectory is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tramhao&#x2F;termusic&quot;&gt;&lt;code&gt;termusic&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I started on it in &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt;, as that tends to be my preferred language for coding at the moment.
A major issue that I’ve run into is trying to integrate it into the “Now Playing” centre that most platforms have (on Apple platforms this is literally called &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;mediaplayer&#x2F;mpnowplayinginfocenter&quot;&gt;&lt;code&gt;Now Playing&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) - especially on Apple platforms.
iOS (and macOS to some extent) require that integration with Apple frameworks is done using Swift, which is a fine language, just one that I’m not at all familiar with.
There is a crate called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chinedufn&#x2F;swift-bridge&quot;&gt;&lt;code&gt;swift-bridge&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which attempts to solve this issue which I’ve had some limited success with (mostly due to my terrible Swift code), but I think I may still be some way off of getting this working reliably.&lt;&#x2F;p&gt;
&lt;p&gt;As I write this, however, I’ve just discovered a Rust crate called &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;souvlaki&quot;&gt;&lt;code&gt;Souvlaki&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which handles this for you, so hopefully there will be much quicker progress on this front soon.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I don’t think I’ve previously mentioned my faith on this blog at all, partly because I’m always a little bit leery of saying the wrong thing or misrepresenting a view and alienating people.
This is particularly complicated by the fact that my particular faith (evangelical Christianity) has a tendency to be particularly maligned these days, particularly as the issue of sexual identity has come into such focus in the last few decades.&lt;&#x2F;p&gt;
&lt;p&gt;I mention this for two reasons; one that is coding related, one that is related to this blog.
First, I have been looking into good methods of electronically studying the bible and extra-biblical resources (such as Greek dictionaries, commentaries, historical writings and the like).
This is something that is technically available as an existing application, &lt;a href=&quot;https:&#x2F;&#x2F;logos.com&quot;&gt;Logos Bible Software&lt;&#x2F;a&gt;, which actually provides a good value offering for what is being delivered.
I would - however, like a Linux version (despite not currently having a Linux computer), as well as the have the core of the software be free software.
Perhaps there is a system that I could use with something like &lt;a href=&quot;https:&#x2F;&#x2F;calibre-ebook.com&quot;&gt;Calibre&lt;&#x2F;a&gt;, but I’m not familiar enough with it at the moment.
Regardless, its something that has been ticking over in the back of my mind.&lt;&#x2F;p&gt;
&lt;p&gt;Second, I would like to start trying to write down some of my opinions on religious things on this blog, perhaps through doing something like an exegetical study of particular passages.
I’m likely to try to keep away from any controversial or contested issues as I simply do not have the expertise to wade in, but perhaps pointing to people or books that I found helpful on similar subjects may be useful.
This is quite a turn around from my previous position on this (which was effectively “don’t mention or hint it at all), but I think that even if I get things wrong it will be helpful to be able to track how my opinions on these things change over time as I mature as a Christian into the future.
Who knows - it may even be a useful resource to someone else in the future.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Adding dark mode to my blog</title>
        <published>2021-03-17T00:00:00+00:00</published>
        <updated>2021-03-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/adding-dark-mode/"/>
        <id>https://tommoa.me/blog/adding-dark-mode/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/adding-dark-mode/">&lt;p&gt;Being the typical zoomer that I am, dark mode has become an essential component of my digital experience.
Over the many years of late-night gaming and the early onset of myopia from staring at too many screens, the blinding effect of the white backgrounds eventually pushed me into more and more dark-themed applications.
I&#x27;m writing this blog post on a dark-themed computer, running a dark-themed terminal emulator running a dark-themed neovim instance.
Even once this post is finished, I&#x27;ll double check it on my dark-themed browser, before swapping to my dark-themed phone and making sure that things look fine on there.&lt;&#x2F;p&gt;
&lt;p&gt;My love of dark modes has extended into other applications as well.
GitHub has its dark-mode set on by default for me, as does Sourcehut and YouTube.
DuckDuckGo because my primary search engine partly because it gave me easy access to a dark-mode that I could never get working on Google.
I stopped using the Gmail web client last year in favour of terminal-based alternatives partly because I could never get dark-mode to work properly on it.&lt;&#x2F;p&gt;
&lt;p&gt;All of this, and until a little over a week ago, I only had a light theme on my blog.
&lt;em&gt;Scandalous&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The theme that I use for this site (which when I finally publish it will be able to be found &lt;a href=&quot;https:&#x2F;&#x2F;git.sr.ht&#x2F;~tommoa&#x2F;theme&quot;&gt;here&lt;&#x2F;a&gt;) is based on insipx&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;insipx&#x2F;Ergo&quot;&gt;Ergo theme&lt;&#x2F;a&gt;, which is in turn based on &lt;a href=&quot;https:&#x2F;&#x2F;svbtle.com&quot;&gt;svbtle&lt;&#x2F;a&gt;.
It&#x27;s a lovely minimal theme, but unfortunately it only has a light theme.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned above, there are a number of websites which I use with dark-mode enabled, and surely I could just pick one and do what they do?
Well unfortunately for me (but not unfortunately for this post), most of them require local storage of some form in order to retain your mode between sessions.
Changed computers or browsers?
That&#x27;s a revision back to the realm of light-mode for you.
Opened up a private browsing window?
Better hope they&#x27;ve somehow tracked you through there before your eyes begin to burn.&lt;&#x2F;p&gt;
&lt;p&gt;Even some of my favourite blogs (such as &lt;a href=&quot;https:&#x2F;&#x2F;fasterthanli.me&quot;&gt;fasterthanlime&lt;&#x2F;a&gt;) which have a dark-mode use local storage to activate it, and it can &lt;em&gt;extremely&lt;&#x2F;em&gt; temperamental between sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately I can continue to avoid JavaScript on my website thanks to the &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;@media&#x2F;prefers-color-scheme&quot;&gt;&lt;code&gt;@media(prefers-color-scheme)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; feature.
As stated on the MSDN, the &lt;code&gt;prefers-color-scheme&lt;&#x2F;code&gt; media feature can be used to detect if the user has requested a light or dark colour scheme, and allows you to override CSS variables accordingly.&lt;&#x2F;p&gt;
&lt;p&gt;This is actually what &lt;a href=&quot;https:&#x2F;&#x2F;git.sr.ht&#x2F;~sircmpwn&#x2F;core.sr.ht&#x2F;tree&#x2F;e41ac24a9a2169a7498251179ab08c3c5ae6f47c&#x2F;item&#x2F;srht&#x2F;scss&#x2F;base.scss#L335&quot;&gt;Sourcehut does&lt;&#x2F;a&gt; to set its colour scheme, and as such I&#x27;ve based my dark theme on theirs.
I think the blue accent is much more suited to a dark background than red, and vice-versa for a light background.&lt;&#x2F;p&gt;
&lt;p&gt;So, if you are currently seeing this in what looks like dark-mode and would like to see what it looks like in light-mode or vice-versa, it should change to the other dynamically when you change your device theme.
As for me, I&#x27;m going to never look at the light theme of my website again, and pray that it never breaks.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On the experience of good audio</title>
        <published>2020-12-23T00:00:00+00:00</published>
        <updated>2020-12-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/experience-good-audio/"/>
        <id>https://tommoa.me/blog/experience-good-audio/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/experience-good-audio/">&lt;p&gt;I recently started listening to music with my Sennheiser 6XXs after around six months of using nothing but earbuds (Sennheiser Momentums and Momentum True Wirelesses).&lt;&#x2F;p&gt;
&lt;p&gt;Now, I love the sound on my earbuds, especially compared to the many other earbuds that I&#x27;ve tried, something about Sennheiser&#x27;s audio engineering just works particularly well for my musical tastes.
I had found, however, that as time went on I used my earbuds less and less, and was generally more happy to listen to music and podcasts using nothing but the speakers of the device they&#x27;re playing on.
Part of the reason for this is that my Pixel 5 doesn&#x27;t have a headphone jack (although I do have wireless earbuds) and my experience of bluetooth audio on my desktop and laptop (regardless of operating system) has left a lot to be desired, so the easiest common ground was just the speakers.&lt;&#x2F;p&gt;
&lt;p&gt;Since I&#x27;ve restarted my use of my Sennheiser 6XXs, I&#x27;ve spent the days doing nothing but listening to music for the sake of the audio experience, which I never really did with the various earbuds.
The songs I&#x27;m listening to I have heard before, but with the better audio quality and dynamic range comes a whole new range of experience that I simply didn&#x27;t have access to before - and its hard to quantify how much better it is.&lt;&#x2F;p&gt;
&lt;p&gt;I think that&#x27;s part of the reason that &quot;audio quality&quot; is so difficult to sell - it&#x27;s an almost unquantifiable metric that is both incredibly subjective and extremely expensive.
High quality audio gear sells for thousands of dollars, and the curve of how much more needs to be invested for a substantial difference is such that gear that is &quot;good enough&quot; sells for less than a hundred dollars.
How on earth could you convince anyone that hasn&#x27;t already invested into audio gear that it is worth it?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m certainly going to try to start using my headphones more, and that&#x27;s also going to involve a level of investment and care from me.
My house gets extremely dusty (especially in the summer) - which is part of the reason that I put my headphones away in the first place - and so I&#x27;ll have to figure out a way to make using them both easy and largely dust proof.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Moving to zsh</title>
        <published>2020-12-06T00:00:00+00:00</published>
        <updated>2020-12-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/moving-to-zsh/"/>
        <id>https://tommoa.me/blog/moving-to-zsh/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/moving-to-zsh/">&lt;p&gt;I &lt;a href=&quot;https:&#x2F;&#x2F;git.sr.ht&#x2F;~tommoa&#x2F;dots&#x2F;commit&#x2F;6cb67335ee1b2e40cd7d118cc3dd117b68bbbdd1&quot;&gt;recently transitioned away&lt;&#x2F;a&gt; from the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.redox-os.org&#x2F;redox-os&#x2F;ion&quot;&gt;&lt;code&gt;ion&lt;&#x2F;code&gt; shell&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;zsh.org&#x2F;&quot;&gt;&lt;code&gt;zsh&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and I figured it might be a good idea to float some of the advantages and disadvantages that I&#x27;ve found during this time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;advantages&quot;&gt;Advantages&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Mostly POSIX compliant.&lt;br &#x2F;&gt;
I&#x27;ll touch on this more later, but in general the ability have portable scripts that work across systems and shells has been incredibly useful - especially as I expand the number of machines I use and prepare to start working after finishing my masters.
For those wondering, &lt;code&gt;ion&lt;&#x2F;code&gt; is &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.redox-os.org&#x2F;redox-os&#x2F;ion&#x2F;-&#x2F;blob&#x2F;master&#x2F;manual&#x2F;src&#x2F;introduction.md&quot;&gt;explicitly not POSIX compliant&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;I can reclaim the &lt;code&gt;@&lt;&#x2F;code&gt; symbol and not worry as much about quoting &lt;code&gt;ssh&lt;&#x2F;code&gt;.&lt;br &#x2F;&gt;
This is a part of &lt;code&gt;ion&lt;&#x2F;code&gt;&#x27;s lack of POSIX compliance, and it claims the &lt;code&gt;@&lt;&#x2F;code&gt; sigil for use in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.redox-os.org&#x2F;redox-os&#x2F;ion&#x2F;-&#x2F;blob&#x2F;master&#x2F;manual&#x2F;src&#x2F;variables&#x2F;02-arrays.md&quot;&gt;array specific functions and variables&lt;&#x2F;a&gt;.
I&#x27;ve generally found throughout my use of &lt;code&gt;ion&lt;&#x2F;code&gt; that I use array variables much less than I do the &lt;code&gt;@&lt;&#x2F;code&gt; sigil, and getting it back for &lt;code&gt;ssh&lt;&#x2F;code&gt;, &lt;code&gt;git&lt;&#x2F;code&gt; and the like has been a major boon.&lt;br &#x2F;&gt;
(It isn&#x27;t so much that I&#x27;m against arrays per say, just that I&#x27;d prefer that it somehow reused a symbol that&#x27;s already typically used by shells instead of nomming another character)&lt;&#x2F;li&gt;
&lt;li&gt;Its much easier to get setup on new computers.&lt;br &#x2F;&gt;
I&#x27;ve just put &lt;a href=&quot;https:&#x2F;&#x2F;alpinelinux.org&quot;&gt;Alpine Linux&lt;&#x2F;a&gt; on a Raspberry Pi 2B, and have begun migrating some recurring tasks to its crontab.
Last time I checked, &lt;code&gt;ion&lt;&#x2F;code&gt; still had some issues building on arm-based platforms, so unfortunately I can&#x27;t quite port &lt;a href=&quot;https:&#x2F;&#x2F;git.sr.ht&#x2F;~tommoa&#x2F;dots&#x2F;&quot;&gt;my dotfiles&lt;&#x2F;a&gt; to it.
I&#x27;ve also recently completed my masters and will begin working in the middle of January.
Knowing the company that I&#x27;m working for, there&#x27;s a chance that I might be getting one of the new-fangled Apple Silicon Macs, and at the time of writing this post, there are still issues with porting even just the Rust compiler to the new platform.&lt;&#x2F;li&gt;
&lt;li&gt;Completion.&lt;br &#x2F;&gt;
Oh boy this is a big one.
&lt;code&gt;ion&lt;&#x2F;code&gt; &quot;has&quot; completion, in that you can tab complete files and commands.
What it doesn&#x27;t have - however - is the ability to tab-complete arguments (which can be an absolute life-saver) nor other more specific completions such as man pages.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;disadvantages&quot;&gt;Disadvantages&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Slower start times.&lt;br &#x2F;&gt;
I open a &lt;em&gt;lot&lt;&#x2F;em&gt; of shell prompts - anyone who basically lives in the terminal and incessantly uses &lt;code&gt;tmux&lt;&#x2F;code&gt; does.
Something that I&#x27;ve definitely noticed is that the time it takes to open a new window or prompt is much lower with &lt;code&gt;ion&lt;&#x2F;code&gt; than it is with &lt;code&gt;zsh&lt;&#x2F;code&gt; - and indeed hyperfine backs this up.
An invocation of &lt;code&gt;hyperfine &#x27;zsh -i -c &quot;. ~&#x2F;.zshrc; exit&quot;&#x27;&lt;&#x2F;code&gt; takes around 70ms (with approximately half of that being completion pre-processing), whilst running &lt;code&gt;hyperfine &#x27;ion -i -c &quot;source ~&#x2F;.config&#x2F;ion&#x2F;initrc; exit&quot;&#x27;&lt;&#x2F;code&gt; only takes around 20ms.
And that&#x27;s despite my &lt;code&gt;ion&lt;&#x2F;code&gt; config doing more than &lt;code&gt;zsh&lt;&#x2F;code&gt;&#x27;s as well as not being as well optimised.&lt;&#x2F;li&gt;
&lt;li&gt;Visible history completion.&lt;br &#x2F;&gt;
One of my favourite features of &lt;code&gt;ion&lt;&#x2F;code&gt; is that (similar to &lt;code&gt;fish&lt;&#x2F;code&gt;) it shows you the most recent matching command in your prompt.
As of yet, I haven&#x27;t been able to figure out a way enable a similar behaviour in &lt;code&gt;zsh&lt;&#x2F;code&gt; without loading an extension module, which has me weary due to the potential additional startup latency I might end up with.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;I think I&#x27;m probably going to stick with &lt;code&gt;zsh&lt;&#x2F;code&gt; until I find a better shell to move to.
Something like &lt;a href=&quot;https:&#x2F;&#x2F;mrsh.sh&quot;&gt;&lt;code&gt;mrsh&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; seems like a great idea of something to move to eventually, especially as &lt;code&gt;dash&lt;&#x2F;code&gt; will likely never implement any form of completion, whilst &lt;code&gt;imrsh&lt;&#x2F;code&gt; names good completion as one of its goals.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, one of &lt;code&gt;ion&lt;&#x2F;code&gt;&#x27;s major advertised features - its inbuilt data structures - are actually something that I&#x27;ve found myself rarely using, especially whilst actually at the shell.
I usually find that should a hashmap or the like be required, then that script should probably be converted to a language like Python, even if only for clarity and the rich inbuilt libraries.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Seminar talk</title>
        <published>2020-10-07T00:00:00+00:00</published>
        <updated>2020-10-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/masters-research/seminar-talk/"/>
        <id>https://tommoa.me/masters-research/seminar-talk/</id>
        
        <content type="html" xml:base="https://tommoa.me/masters-research/seminar-talk/">&lt;p&gt;Hello, I’m Tom Almeida, and I’m going to be presenting on code
optimization of a gravitational wave detection pipeline a project that
I’ve been working on for the last six months.&lt;&#x2F;p&gt;
&lt;p&gt;But before we actually get into the content of my research, we should
have a quick look at how this report is going to be structured.&lt;&#x2F;p&gt;
&lt;p&gt;I’m going to walk through each of the major areas that my research has
focused on. These are and I promise to expand on what these words
actually mean once I get to them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;N-detector implementation; and&lt;&#x2F;li&gt;
&lt;li&gt;Post-processing complexity analysis&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, we’ll finish by looking at the platform that this project gives
for future research.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;n-detector&quot;&gt;N-detector&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;gravitational-waves&quot;&gt;Gravitational Waves&lt;&#x2F;h3&gt;
&lt;p&gt;So let’s begin by looking at some background information what are
gravitational waves?&lt;&#x2F;p&gt;
&lt;p&gt;You may have heard of a little thing called the “general theory of
relativity”, which Albert Einstein published in 1916 as a way to
integrate gravity into the concept of space-time. Gravitational waves
are ‘ripples’ in the fabric of space-time caused by some of the most
powerful processes in the universe - things like colliding black holes,
exploding stars and the birth of the universe are all things that emit
gravitational waves. Their existence was predicted in 1916 as a
derivation of Einstein’s theory of general relativity, which showed that
massive accelerating objects such as orbiting neutron stars or black
holes would disrupt space-time in such a way that waves of distorted
space would radiate from the source.&lt;&#x2F;p&gt;
&lt;p&gt;Detection of gravitational waves is done using interferometers, using
the timing difference between massive lasers to determine if space-time
has been distorted. Now the way that these detectors actually work and
the physics behind all of this isn’t really relevant to my research, so
the most important thing to know about these detectors is that they emit
a lot of data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;processing-pipelines&quot;&gt;Processing Pipelines&lt;&#x2F;h3&gt;
&lt;p&gt;To deal with all this data, processing pipelines were created to sift
through the noise and find the gravitational waves.&lt;&#x2F;p&gt;
&lt;p&gt;One of these is the Summed Parallel Infinite Impulse Response pipeline
(which I’m going to call SPIIR), which uses a combination of IIR filters
(known as a “template”) to approximate gravitational waves. It’s
currently thought to be one of the lowest latency pipelines of those
existing, and is almost fast enough to enable prompt follow-up
observation on gravitational wave events with traditional telescopes.&lt;&#x2F;p&gt;
&lt;p&gt;A major problem with the SPIIR pipeline (and all the other existing
pipelines as well) is that only supports a fixed number of detectors,
and the process of adding extra detectors to be processed is an
incredibly time consuming process. A number of new detectors are coming
online in the next few years, so figuring out a way to do this better is
vital to ensuring that the pipeline can continue to operate.&lt;&#x2F;p&gt;
&lt;p&gt;This is the first part of my project, to allow the pipeline to run with
any number of detectors with minimal change to the codebase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-power-of-powers-of-2&quot;&gt;The power of powers of 2&lt;&#x2F;h3&gt;
&lt;p&gt;Internally, the pipeline uses an array to keep track of which detectors
it is processing, and this array is called the IFOComboMap (which you
can see on the screen). We can think of this map (in its current state)
as being ordered as the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All single detectors&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;All combinations of two detectors&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;All combinations of three detectors&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;So on&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This gives us a problem when adding new detectors, because let’s say we
add one more detector, then suddenly the indexing would change for more
than half of the combinations!&lt;&#x2F;p&gt;
&lt;p&gt;To solve this problem, we can think about how detectors are used in a
slightly different way. Detectors (as you might be able to tell from the
combination map) are either used or unused and critically the ordering
doesn’t matter. We’re talking about combinations here, and not
permutations. One way to count the number of combinations with \(N\)
objects is to count every number of to \(2^N\).&lt;&#x2F;p&gt;
&lt;p&gt;Let’s use an example. Say we have 5 elements, and we want to represent
every combination of those elements, we can represent it with a binary
number with 5 bits. If I want to have only the first element selected in
my combination, then I can simply flip it from 0 to 1. I can do the same
if I want my combination to be the first and third elements, as well as
the first, third and fifth elements.&lt;&#x2F;p&gt;
&lt;p&gt;We can use this information to make a table that doesn’t change indexing
at all when we add extra elements, by having each index be the number
that would represent that combination if it were a power of two. It
looks like this. And this is what it looks like now that we add
detectors. Much better!&lt;&#x2F;p&gt;
&lt;p&gt;There’s a few extra fun properties that we get from representing our
combination like this. First, we can always tell how many detectors are
being used by checking the number of flipped bits in our combination. We
can do this super efficiently by using the x86 instruction “popcount”,
which should be even faster than a comparison (which you’d have to have
done before). We can also check to see whether a particular detector is
being used by checking to see if the bit corresponding to it has been
flipped.&lt;&#x2F;p&gt;
&lt;p&gt;Making this change was actually relatively modest, with about 400 lines
of code modified. Unfortunately, that’s not quite the end of the game
for letting the pipeline handle any number of detectors!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-hunt-for-hardcoded-detectors&quot;&gt;The hunt for hardcoded detectors&lt;&#x2F;h3&gt;
&lt;p&gt;The pipeline passes around data structures with hardcoded names to each
of its components. Fortunately, because C allows for fixed size arrays
in data structures, this is quite a simple change, but unfortunately
means that &lt;em&gt;everything&lt;&#x2F;em&gt; that references any of these tables needs to
change in order to work with any number of detectors. So all in all,
this ended up being around 1000 lines of code changed.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately we don’t have the time to dive into some of the technical
things here about how this change interacts with the pipeline’s Python
or some of the other things, but feel free to come back to it in
question time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;complexity-analysis&quot;&gt;Complexity analysis&lt;&#x2F;h2&gt;
&lt;p&gt;Now we’re going to take a dive into a complexity analysis I did on one
of the components of the pipeline.&lt;&#x2F;p&gt;
&lt;p&gt;We’re going to start with some background information, and then I’ll
talk a bit about why this needed to be done before we get to the
actually juicy things.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;complexity-analysis-1&quot;&gt;Complexity Analysis&lt;&#x2F;h3&gt;
&lt;p&gt;Alright, so now let’s actually have a look at what a complexity analysis
is.&lt;&#x2F;p&gt;
&lt;p&gt;Complexity (or asymptotic) analysis is an analytical approach to
understanding how the performance of an algorithm or data structure
scales (or grows) with the size of its input. As UWA’s very own CITS2200
(which this slide is ripped from) puts it, it allows us to compare
algorithms and observe performance barriers. Complexity analysis of
parallel algorithms is a little different to the sequential algorithms
you may be used to, and so we need to define some terms.&lt;&#x2F;p&gt;
&lt;p&gt;First of all, we can consider a parallel algorithm to be a directed
acyclic graph of sequential work, which we eventually combine to create
some final answer. As our example up there, we have up there the
“mergesort” algorithm and the work to complete each node up to the
final combining node.&lt;&#x2F;p&gt;
&lt;p&gt;The “work” of a parallel algorithm is the same as though we attempted to
execute the entire computation sequentially. So for this example, that
would be \(O(N log N)\) (assuming we drew back enough nodes). We can
find the “work” by summing up all the individual nodes together. A
useful way to think about work is that it is equivalent to running the
entire algorithm with just one processor and thus it would be
sequential.&lt;&#x2F;p&gt;
&lt;p&gt;The “span” of a parallel algorithm is the maximum time taken to complete
any path in the DAG. So for this example, if we follow the path of the
top edge, we can find that the “span” of mergesort would be
\(O(2N) = O(N)\).&lt;&#x2F;p&gt;
&lt;p&gt;Finally, we need to have some way of seeing practically what this means
for us for runtimes. Brent’s theorem is a handy way to combine our work
and span with an actual number of \(P\) processors to turn it into an
actual runtime. I’ve used it in my analysis, but we won’t actually see
it in action, just see the end result.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-why-do-we-care-about-this-complexity-analysis&quot;&gt;So why do we care about this complexity analysis?&lt;&#x2F;h3&gt;
&lt;p&gt;Well now that we’ve successfully made it so we can have the SPIIR
pipeline run any number of detectors, we need to figure out what that
means for the speed of SPIIR. Remember that SPIIR is designed to be
low-latency, so if adding too many more detectors slows things down,
then it’ll cause problems later on down the line.&lt;&#x2F;p&gt;
&lt;p&gt;We can see the components that we need to check for problems with extra
detectors by taking another look at this data flow graph, which we can
simplify further to this. Only the components after all the data flow
combines need to be checked to make sure they’ll deal with the extra
detectors fine.&lt;&#x2F;p&gt;
&lt;p&gt;But before we get into the analysis, we need to look at CUDA, and how it
plays with analysing parallel programs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cuda&quot;&gt;CUDA&lt;&#x2F;h3&gt;
&lt;p&gt;The SPIIR pipeline uses NVIDIA’s CUDA, a parallel programming interface
for GPU acceleration, and the section of code that I’ll be analysing
today will be using CUDA so its worth taking a quick look at how it
works so we can understand what’s going on.&lt;&#x2F;p&gt;
&lt;p&gt;GPUs lend themselves really well to parallel code, as whilst they have
very little memory per-processing core, they have orders of magnitude
more processing cores than traditional CPUs. This heavy focus on
parallel code results in a slightly different computational model.&lt;&#x2F;p&gt;
&lt;p&gt;In CUDA, each individual sequence of instructions being executed is
called a thread. These threads are partitioned into warps, which are a
group of 32 threads. Warps are the smallest unit of threads that a GPU
can run, and all threads within a warp must execute the same
instructions. Warps are then further organised into thread blocks, which
are run on simultaneous multiprocessors and contain a small amount of
fast memory that can be shared between the threads in the block. The
region of data that is being processed can be further split by
organising blocks into ‘grids’, although grids have no actual relation
to a physical computation unit.&lt;&#x2F;p&gt;
&lt;p&gt;Conceptually speaking, every thread is a node that goes to every block,
that goes to every grid. As such, we can “parallelise” things by
splitting the work into many nodes by using threads, blocks or grids as
our splitting mechanism.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;analysis&quot;&gt;Analysis&lt;&#x2F;h3&gt;
&lt;p&gt;My first job was to figure out how and when all the functions were
called, and by who. To do this, I wrote my own C&#x2F;C++&#x2F;CUDA compiler
wrapper to generate a callgraph of which function calls what.&lt;&#x2F;p&gt;
&lt;p&gt;Now that I had my callgraph, I could use the techniques that I used
above to determine what the total asymptotic complexity analysis was.&lt;&#x2F;p&gt;
&lt;p&gt;And this is what I ended up with. I’m sure that we can all stare at
those final results all day and try to make heads and tails of it, but
here’s the important part it turns out that SPIIR’s post-processing
deals with additional detectors kind of badly.&lt;&#x2F;p&gt;
&lt;p&gt;Because we currently use three detectors, the cubic term here means that
we could potentially end up with around a 2.4x slow down of this
component just for adding a detector.&lt;&#x2F;p&gt;
&lt;p&gt;This segues nicely into the future work that can be done to build on
this research.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;&#x2F;h2&gt;
&lt;p&gt;There are several future directions for this research to explore. One
way to counter the potential slow down of adding new detectors is to
simply have extra detectors skip the post-processing step.&lt;&#x2F;p&gt;
&lt;p&gt;This would change the structure of the pipeline from this, to this. So
long as the pipeline is still able to detect gravitational waves with
the remaining detectors, we can use these skipping detectors for
localization that is figuring out where the gravitational wave comes
from. This is already being worked on, and should be ready to go in a
few months time.&lt;&#x2F;p&gt;
&lt;p&gt;Another option is to take a further look at algorithms used in the
post-processing. It may be possible that parallelisation around the
number of detectors may be possible, which could potentially cause a
large speedup, as even dropping from \(D^3\) to \(D^2\) brings the
slowdown from extra detectors down significantly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;et-fin&quot;&gt;Et fin.&lt;&#x2F;h2&gt;
&lt;p&gt;Anyway, that’s about it from me, are there any questions?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The different approaches between `emacs` and `vim` packages</title>
        <published>2020-09-30T00:00:00+00:00</published>
        <updated>2020-09-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/emacs-and-vim-packages/"/>
        <id>https://tommoa.me/blog/emacs-and-vim-packages/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/emacs-and-vim-packages/">&lt;p&gt;I recently tried using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&quot;&gt;&lt;code&gt;emacs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for the first time in many years (the last time I used &lt;code&gt;emacs&lt;&#x2F;code&gt; was back in early 2017, and I moved to using &lt;code&gt;vim&lt;&#x2F;code&gt; later that year).
Many of my colleagues at my last internship use &lt;code&gt;emacs&lt;&#x2F;code&gt; - there was even an internal minor mode for editing and using many of the internal tools - and a number of friends at university are also &lt;code&gt;emacs&lt;&#x2F;code&gt; evangelists, so I thought that it&#x27;d be a good idea to re-acquaint myself with the editor that I left behind.&lt;&#x2F;p&gt;
&lt;p&gt;Long story short - I&#x27;ve decided to stick with &lt;code&gt;neovim&lt;&#x2F;code&gt;.
There&#x27;s actually a bunch of reasons why (which I can probably go into at a later date), but my brief foray back into the world of &lt;code&gt;emacs&lt;&#x2F;code&gt; showed me an interesting difference in philosophy between &lt;code&gt;emacs&lt;&#x2F;code&gt; and &lt;code&gt;vim&lt;&#x2F;code&gt; packages.&lt;&#x2F;p&gt;
&lt;p&gt;As someone who (of course) wants to use &lt;code&gt;vim&lt;&#x2F;code&gt; bindings in every text editor that I use, I of course installed &lt;code&gt;evil-mode&lt;&#x2F;code&gt;, the &lt;code&gt;vim&lt;&#x2F;code&gt; compatibility layer for &lt;code&gt;emacs&lt;&#x2F;code&gt;.
This went along quite swimmingly until I had to install other packages, all because they all automatically overrode keybinds.&lt;&#x2F;p&gt;
&lt;p&gt;This was a pattern that tended to find throughout my &lt;code&gt;emacs&lt;&#x2F;code&gt; experience.
Packages create their own major or minor mode, and then provide a number of key-binds within that mode to interface with its functionality - which can cause a lot of problems for me when I&#x27;ve remapped a good number of the keys because I don&#x27;t use a QWERTY keyboard.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s become like a game for me.
See how many plugins I can find that all try to override the same key-bind.&lt;&#x2F;p&gt;
&lt;p&gt;In my experience, &lt;code&gt;vim&lt;&#x2F;code&gt; packages have the exact opposite approach - although I will fully admit to not using very many packages.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neoclide&#x2F;coc.nvim&quot;&gt;&lt;code&gt;coc.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, for example, doesn&#x27;t set any keybinds and instead requires the user to assign their own binds to the functions that it provides.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;fzf&quot;&gt;FZF&lt;&#x2F;a&gt; does exactly the same thing, as does &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;liuchengxu&#x2F;vista.vim&quot;&gt;&lt;code&gt;vista.vim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This has actually been really surprising to me, as I would have likely expected the exact opposite.
I often hear &lt;code&gt;emacs&lt;&#x2F;code&gt; talked about as being an &quot;elisp interpreter with an editor attached&quot; - which to me suggests that the primary focus of &lt;code&gt;emacs&lt;&#x2F;code&gt; would be on elisp functions - whereas &lt;code&gt;vim&lt;&#x2F;code&gt;&#x27;s major selling point is its excellent keybindings.&lt;&#x2F;p&gt;
&lt;p&gt;I think that if &lt;code&gt;emacs&lt;&#x2F;code&gt; packages had taken a similar approach to what &lt;code&gt;vim&lt;&#x2F;code&gt; packages seem to - that I&#x27;d have expected them to take - then I&#x27;d almost certainly switch to &lt;code&gt;emacs&lt;&#x2F;code&gt; for the additional flexibility of having the power of lisp at my fingertips.
As it is, however, it would take far too much work every time I install a package for me to want to move.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tracking myself</title>
        <published>2020-09-20T00:00:00+00:00</published>
        <updated>2020-09-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/tracking-myself/"/>
        <id>https://tommoa.me/blog/tracking-myself/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/tracking-myself/">&lt;p&gt;Partly inspired by &lt;a href=&quot;https:&#x2F;&#x2F;julian.digital&quot;&gt;Julian Lehr&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;http:&#x2F;&#x2F;julian.digital&#x2F;activity&#x2F;life-logging&#x2F;&quot;&gt;quantified self&lt;&#x2F;a&gt;, I&#x27;m planning on trying to track myself.
I don&#x27;t expect that I&#x27;ll actually start on this for a while, as there are a number of tools I have to figure out before I can properly get into the swing of things, but I figured that it&#x27;d be worth writing down my reasons why I want to do this.
In future weeks, I&#x27;ll cover how I&#x27;m building the tools to let me track myself.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m generally a pretty privacy-focused person.
Any applications that I use always have telemetry turned off, my social media is basically whisper quiet unless its via private messages, and I even borrowed a laptop from the university so I wouldn&#x27;t have to use exam software that required root privileges on my own hardware.&lt;br &#x2F;&gt;
Tracking myself - and posting it on this blog like Julian Lehr does - seems to run pretty contrary to all sorts of privacy principles.
So why on earth would I want to do it?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve always sort of considered myself a numbers guy.
In primary school (in Australia, that&#x27;s ages 4-12), I was &lt;em&gt;the&lt;&#x2F;em&gt; &quot;math guy&quot; in the class, and had by far the best marks in maths in my school (although I don&#x27;t think I even made the top quartile in high school), and have always found maths that I can apply to be fun and interesting.
It&#x27;s part of the reason that I got into programming in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m also generally well convinced by numbers that are put before me in order to inspire some continued positive action.
Watching the numbers on the weights at the gym go up, how good I felt as I ran 5km slightly faster than before, and my weight go down (even if only a bit) has encouraged me to regularly exercise far more than the nebulas &quot;it&#x27;s good for you&quot; that my parents always told me throughout my teenage years.&lt;&#x2F;p&gt;
&lt;p&gt;As such, I am somewhat convinced that tracking myself - and watching trends for various metrics of how my time is spent - will help me be able to narrow down and improve things that in my life.
Perhaps I can see if I&#x27;ve spent too long on a particular weight at the gym, and should go to the next weight up.
Maybe I can spot transport routes that would be slightly more efficient than what I currently have.
I could even find that I spend half my time doing nothing useful at all, and thus need to come up with strategies to improve productivity.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s an extent to which doing this is good for my privacy as well.
By tracking myself, I will be able to get a better understanding of what sort of data companies have on me.
My smart-watch (a Garmin VivoActive 4) will probably be used for most of the data, and frankly the amount of data that it can&#x2F;does have on me is slightly terrifying - especially now that I&#x27;ve gone through what I can get from Garmin&#x27;s API.
I&#x27;ll be able to go digging to see what Amazon has on me (Kindle&#x2F;Audible), what Google has figured out (Android&#x2F;Google Assistant), and how Spotify could figure me out.
In the process of tracking myself, I&#x27;ll become more aware of how others can track me too.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, as long as my data isn&#x27;t &lt;em&gt;too&lt;&#x2F;em&gt; fine-grained, privacy shouldn&#x27;t be too much of an issue.
I don&#x27;t plan on writing detailed logs of exactly where I&#x27;ve been - if my house shows up anywhere, then you know that my data collection has gone too far.
I don&#x27;t even plan on sharing any GPS-type metrics at all, save what city I&#x27;m in.&lt;&#x2F;p&gt;
&lt;p&gt;I imagine that it might take me some time to be able to even get the right sort of data for any useful analysis, and whilst I don&#x27;t really know what I might find out, but I&#x27;m excited to see!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The changing scope of my research</title>
        <published>2020-09-13T00:00:00+00:00</published>
        <updated>2020-09-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/changing-research-scope/"/>
        <id>https://tommoa.me/blog/changing-research-scope/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/changing-research-scope/">&lt;p&gt;I started on my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;masters-research&#x2F;&quot;&gt;Masters research project&lt;&#x2F;a&gt; back in March, and the progress of both the project itself and how I&#x27;ve felt about it since that time has been somewhat interesting.&lt;&#x2F;p&gt;
&lt;p&gt;For some context, the codebase that I&#x27;ve been contributing to as a part of my research is approximately 50 thousand lines of code long, and the PhD thesis that much of my work is based on is 204 pages long (as I&#x27;ve &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;non-essay-word-count&#x2F;&quot;&gt;previously mentioned&lt;&#x2F;a&gt;), so even getting a grasp on &lt;em&gt;what&lt;&#x2F;em&gt; exactly research project entailed took quite a long time.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst students do pick their own research projects (and I selected the research team that I joined), the projects themselves are selected by the supervisors and then advertised.
This unfortunately meant that whilst my supervisor had somewhat of a grasp on the project that I had selected, I myself had basically no clue.
I have no background in physics (the most that I&#x27;ve done is high school physics, and definitely nothing to do with gravitational waves), so even understanding how everything fit together to do what it was intended to do was incredibly difficult - and it was made worse by the fact that the codebase has very few comments.&lt;&#x2F;p&gt;
&lt;p&gt;As such, a large part of my time up until now was simply me trying to get up to speed.
I did a &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;masters-research&#x2F;analysis.pdf&quot;&gt;complexity analysis of a part of the codebase&lt;&#x2F;a&gt;, with the sole purpose of attempting to understand the small section which that analysis encompassed.
It definitely worked, but as time has continued and I&#x27;ve gotten a better idea of how everything fits together, it turned out that the section of code I analysed actually has little to do with my main part of my research - so all that work was for nothing.&lt;&#x2F;p&gt;
&lt;p&gt;To me, it always felt like the scope of my project was changing, even though in actually that scope never changed.
More files moved into what felt like the scope of my project at exactly the same time other files were suddenly discounted.
I went from expecting my entire project to be in C and CUDA to it being in only Python, and then back again.
Most of this change was because of my understanding of what exactly my project entailed didn&#x27;t fully mature until I had a full understanding of how everything was put together, and that understanding was vital to figuring out &lt;em&gt;how&lt;&#x2F;em&gt; exactly I was meant to go about solving the problem I was given.&lt;&#x2F;p&gt;
&lt;p&gt;I think that this is likely the case for lots of people in more theoretical research than my more implementation-focused research.
As your understanding of the thing you are researching increases, the more likely it is that things that you may have previously thought important suddenly become irrelevant, and ideas that only seemed to be tangential are suddenly vital - and this seems to be the pattern of any complex long-term project.&lt;&#x2F;p&gt;
&lt;p&gt;I think that this is part of the reason why senior (or at least experienced) software engineers are so coveted.
Whilst they may not be &lt;a href=&quot;https:&#x2F;&#x2F;swizec.com&#x2F;blog&#x2F;why-senior-engineers-get-nothing-done&#x2F;&quot;&gt;burning many story points&lt;&#x2F;a&gt; for their own managers to see, they have enough experience with the codebase and exposure to different ways to solve problems to be able to make the scope for other people much smaller, and their entire team more efficient because of it.
It&#x27;s also why there&#x27;s always an &quot;on-boarding&quot; period for new employees, so they are able to have a rudimentary understanding of the potential scopes of any problems they encounter.&lt;&#x2F;p&gt;
&lt;p&gt;With this in mind, I think there&#x27;s a few items that I think massively help with preventing the sort of scope creep that I&#x27;ve experienced.
In many ways these are probably just some more common sense general guidelines, and can probably be found in any &quot;programming processes&quot; textbook, but will still be helpful to list here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;have-useful-comments-and-documentation&quot;&gt;Have useful comments and documentation&lt;&#x2F;h3&gt;
&lt;p&gt;The codebase I&#x27;ve been working on has very &lt;em&gt;very&lt;&#x2F;em&gt; few comments, and those that it does have are generally just commenting out old versions of the code.
This means that almost all the sources for how things work need to come from outside the codebase itself, and are usually one of two things - people or papers (as in peer-reviewed papers).&lt;&#x2F;p&gt;
&lt;p&gt;The massive downside to this is that if you want to find out how one very specific part of the codebase works, you either need to have someone who hasn&#x27;t worked on that part of the code for potentially many years sit down and work through it with you, or you need to trawl one of 50 research papers in the hope that it mentions the specific function that you&#x27;re looking for (and spoiler alert, chances are that none of them do).
Having no useful comments and no useful documentation means that the process of on-boarding is incredibly time consuming and takes valuable work hours away from people that know the codebase well in order to explain the minutia of the code to the newcomers.&lt;&#x2F;p&gt;
&lt;p&gt;This is something that I&#x27;ve attempted to rectify with my research project - every addition has been commented on in its function and sometimes how&#x2F;why it works.
My hope is that the next person that needs to work on the same area of code would be able to make use of the work I&#x27;ve already done and not need to retrace my steps, but unfortunately the entire codebase is so massive in comparison to the scope of my work that the chance of any overlap is minute.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;have-useful-commit-messages&quot;&gt;Have useful commit messages&lt;&#x2F;h3&gt;
&lt;p&gt;This is another area that definitely needed improving.
Before I began on this research project, commit messages often looked like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#6c7079;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;postcoh.c: fix a bug for output trigger-&amp;gt;ifos when the ifos are LV
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#6c7079;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;generic_init.sh: change Virgo quality bits with latest suggestion
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the first one, what was the bug?
How does this change fix it?
Or for the second one, what&#x27;s the &quot;latest suggestion&quot;?
What problem does it solve?&lt;&#x2F;p&gt;
&lt;p&gt;The commit messages that are in the repository are as useful documentation as the comments in the code themselves in many cases.
If you can clearly articulate the reasoning behind changes, the problems that they solve and perhaps possible alternatives, then it makes understanding the progression of the codebase significantly easier - and running &lt;code&gt;git blame&lt;&#x2F;code&gt; actually would return useful information.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to writing commit messages, I try to follow this &lt;a href=&quot;https:&#x2F;&#x2F;chris.beams.io&#x2F;posts&#x2F;git-commit&#x2F;&quot;&gt;excellent blog post on commit messages&lt;&#x2F;a&gt;, which suggests that you should try to use a text body of a commit message whenever possible to explain &quot;what&quot; and &quot;why&quot; the change has been made.
There&#x27;s also been a push from some of the other members of the research team to follow similar guidelines.
The project goes under an external code review every 1.5 years or so, and being able to clearly show the reasoning for changes is something that helps with the efficiency of that review in addition to helping new team members understand what they&#x27;re looking at.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;provide-early-and-timely-feedback-to-direct-efforts&quot;&gt;Provide early and timely feedback to direct efforts&lt;&#x2F;h3&gt;
&lt;p&gt;One of the reasons why the area of code that I did a complexity analysis on ended up being irrelevant for my project is because I had absolutely no idea what I was being asked to do in my project.
I&#x27;d written a project proposal, had talked to my supervisors about doing a complexity analysis, did the complexity analysis, and the only feedback that I got the entire time was &quot;no one has done a complexity analysis for this type of project before, I look forward to the results!&quot;.
Whilst this was nice to hear, and the complexity analysis was fun to do, it felt all for naught when I realised that it wasn&#x27;t really under the purview of my project.
The many hours that I spent pouring over that part of the code, trying to understand every part and running some of my own benchmarks and performance analysis ended up being for something entirely irrelevant.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t think that this is entirely the fault of my supervisors - a large part of it also falls on to me for not clarifying what exactly was being asked of me, especially as I didn&#x27;t really understand how the whole project fit together at the time - but some early feedback to properly direct my efforts into something that was actually relevant would have allowed me to finish my project significantly earlier than it was, and possibly even have time to extend the project.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;I know I&#x27;ve spent the last thousand or so words complaining about things in my research project, but I have genuinely enjoyed my time doing research this year.
The value of good comments and documentation, commit messages and the role of feedback in directing efforts are lessons that I will take onto my future projects and work to ensure that the feeling of massively changing scope in a static project does not happen again to me, nor anyone else.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rescheduling when I do blog posts</title>
        <published>2020-09-01T00:00:00+00:00</published>
        <updated>2020-09-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/rescheduling-blog-posts/"/>
        <id>https://tommoa.me/blog/rescheduling-blog-posts/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/rescheduling-blog-posts/">&lt;p&gt;It&#x27;s been almost a full week since my last blog post, and I should probably discuss why.&lt;&#x2F;p&gt;
&lt;p&gt;When I originally restarted this blog, I &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;a-new-start&#x2F;&quot;&gt;intended to write one blog post per day&lt;&#x2F;a&gt;.
Barely three weeks later and it seems like I&#x27;ve given up all hope of trying for that trend.&lt;&#x2F;p&gt;
&lt;p&gt;I found, not long after I started, that when I wrote about things that I&#x27;d given some thought to, &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;non-essay-word-count&#x2F;&quot;&gt;I wrote a lot more words than I thought I would&lt;&#x2F;a&gt;.
Unfortunately, I am limited by my ability to type fast and get my words onto my computer.
This often means that even if I have a fully-formed and planned out idea, it can easily take me 45 minutes to an hour to write.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m almost the entire way through my Masters, and the semester truly has gotten back into the swing of things.
I have mid-semester tests coming up, and assignment are beginning to become due.
In addition, my thesis will soon need to be submitted, which means that for me, my time is at a premium.&lt;&#x2F;p&gt;
&lt;p&gt;As such, I&#x27;m instead going to move to writing one blog post a week, starting next week on Sunday.
I think this should give me the time to be able to spend on my other assignments and allow me to properly spend the time on these posts.&lt;&#x2F;p&gt;
&lt;p&gt;I should probably say that this one blog post a week isn&#x27;t due to a lack of ideas - I almost have more ideas written down than I have taken days off writing!
Unfortunately, I just need to put more time into my university work for the moment.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My ideal computer at the moment</title>
        <published>2020-08-26T00:00:00+00:00</published>
        <updated>2020-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/ideal-pc-2020/"/>
        <id>https://tommoa.me/blog/ideal-pc-2020/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/ideal-pc-2020/">&lt;p&gt;Chris Siebenmann recently wrote about &lt;a href=&quot;https:&#x2F;&#x2F;utcc.utoronto.ca&#x2F;~cks&#x2F;space&#x2F;blog&#x2F;tech&#x2F;MissingPCType&quot;&gt;how is ideal machine isn&#x27;t in an existing category&lt;&#x2F;a&gt;.
Interestingly, I find myself in the same sort of situation, however with an almost entirely different conclusion.&lt;&#x2F;p&gt;
&lt;p&gt;As I have &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;multiple-machines-are-hard&#x2F;&quot;&gt;previously mentioned&lt;&#x2F;a&gt;, I am of the opinion that as the number of machines you try to do work on increases, the ease of synchronization between those machines increases exponentially.
This means that for me, an ideal machine would be easily portable so that it can be used anywhere with minimal effort to transport.
This effectively pushes me into a being left with the options of either a laptop (as in an ultrabook) or a tablet.&lt;&#x2F;p&gt;
&lt;p&gt;Tablets are in an interesting position right now where they are continuously increasing in power and ability, but still lack many of the features that I&#x27;d require in a daily driver machine, namely the ability to easily compile code locally, easy access to the terminal and a keyboard-driven UI (tiling window managers truly have gotten the better of me).
Thus, I am left with the sole choice of a laptop.&lt;&#x2F;p&gt;
&lt;p&gt;Now the nitpicking starts, what sort of specs do I want in a laptop?
Well, as you may have picked up from my rant about &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;esports-wont-be-mainstream&#x2F;&quot;&gt;why esports will never be mainstream&lt;&#x2F;a&gt;, I play CS:GO on a regular basis, and also enjoy casually playing a number of other single-player games such as BioShock and Civilization.
As such, I would quite like to be able to continue playing these games as I use them as my primary source of leisure.&lt;&#x2F;p&gt;
&lt;p&gt;Say what you will about their power, but gaming laptops are both (generally speaking) incredibly heavy and immobile, and very difficult to upgrade.
I have no intention of needing to update my laptop every 1-2 years just so I can upgrade my GPU.
So for me, the option that makes the most sense is a laptop with an external GPU enclosure, so the GPU can be upgraded independently of the rest of the machine.
This would also allow me to dock my machine when I get home and be able to get use out of the high refresh rate monitors that I own - something that would be extremely valuable for gaming.
External GPU enclosures do exist on the market (although they are not widely used), however they are almost all based on Thunderbolt 3.
This leads me to my next problem.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d much rather use an AMD-based than an Intel-based CPU, as the current generation of Ryzen-based laptop CPUs run circles around their Intel equivalents.
With the addition of their extra cores, both compiling and gaming would be significantly better on an AMD-based laptop than Intel-based laptop.
This comes with the issue of USB 4 (the equivalent Thunderbolt 3 standard which can be used for external GPU enclosures) only being supported on the next-generation of AMD chips.&lt;&#x2F;p&gt;
&lt;p&gt;Thus my ideal machine doesn&#x27;t yet exist, but I fully expect that in a year or two it might.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Turns out you can get in contact with me</title>
        <published>2020-08-25T00:00:00+00:00</published>
        <updated>2020-08-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/contact-or-feedback/"/>
        <id>https://tommoa.me/blog/contact-or-feedback/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/contact-or-feedback/">&lt;p&gt;Today&#x27;s update will be a fair bit shorter than my usual fair (thank goodness!).&lt;&#x2F;p&gt;
&lt;p&gt;I mentioned in &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;contact-without-social-media&#x2F;&quot;&gt;this post&lt;&#x2F;a&gt; that there would be no way to contact me easily for feedback and comments.
My belief at the time of writing was that if I wanted to receive emails from an email address related to this domain (e.g. &lt;code&gt;something@tommoa.me&lt;&#x2F;code&gt;), I&#x27;d have to purchase a domain email service.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out, I&#x27;m wrong about that.
I&#x27;ve been able to setup &lt;a href=&quot;mailto:&#x2F;&#x2F;tom@tommoa.me&quot;&gt;tom@tommoa.me&lt;&#x2F;a&gt; to send me email, but unfortunately there&#x27;s been no way (as far as I can tell) for me to be able to send mail back using that address unless I pay for email.
From my hosting provider, it only costs about $2 AUD per month for email (compared to GSuite at $8.50 AUD per month), but I don&#x27;t want to waste even $2 if it turns out that the email address isn&#x27;t going to be used.&lt;&#x2F;p&gt;
&lt;p&gt;If I start getting enough email through the address above that it becomes worth it to me to buy purchase the domain, I will, but as my current audience (as far as I&#x27;m aware) is a grand total of zero people, it&#x27;s definitely not worth my money right now.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Automatically updating git submodules using GitHub Actions</title>
        <published>2020-08-24T00:00:00+00:00</published>
        <updated>2020-08-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/github-auto-update-submodules/"/>
        <id>https://tommoa.me/blog/github-auto-update-submodules/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/github-auto-update-submodules/">&lt;p&gt;I know that the mono-repository is in style at the moment, but &lt;code&gt;git&lt;&#x2F;code&gt; submodules are a fantastic (and probably over complicated) tool for being able to store components of a git repository that may need to be kept used, but separate.
For example, you may need to track a specific upstream version of another repository that isn&#x27;t controlled by you or your organization for use in your repository, or you might want to mix repository visibility or share some code between different repositories that need to be separated.&lt;&#x2F;p&gt;
&lt;p&gt;I personally use submodules in the repositories for a wide variety of uses.
For example, my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Tommoa&#x2F;ozgrav-research&quot;&gt;research project&lt;&#x2F;a&gt; uses a submodule to track the latest version of the codebase that I am modifying so I can write patches to match against those versions.
Another example is my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&quot;&gt;site&lt;&#x2F;a&gt;, which has a bunch of submodules to track various things which get published there, from my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;cv&#x2F;cv.pdf&quot;&gt;resume&lt;&#x2F;a&gt; and my research project, to the theme that I use for both my site and this blog.&lt;&#x2F;p&gt;
&lt;p&gt;I only recently moved to using the same codebase for the theme of my site and blog, which has both made my life easier and caused me a great deal of heartache - and almost all of the heartache came from &lt;code&gt;git&lt;&#x2F;code&gt; submodules.
You see, submodules are tied to a specific commit, and running a command like &lt;code&gt;git submodule update&lt;&#x2F;code&gt; (which you&#x27;d think updates a submodule to the latest version) only checks out the submodule to the same commit as what your local repository already has stored.
This makes life a little more difficult - how can I easily update submodules without having to specifically know the remotes, branches or location of all of my submodules?&lt;&#x2F;p&gt;
&lt;p&gt;First, all of the submodules have their remotes and locations (and optionally branches) stored in the &lt;code&gt;.gitmodules&lt;&#x2F;code&gt; file, which can be used to iterate through the submodules and pull down the latest versions.
Another option is using the &lt;code&gt;git submodule foreach&lt;&#x2F;code&gt; command to update the submodules by fetching the remotes and then checking out latest commit, which has the disadvantage submodules not (by default) being checked out branches, and instead is checked out to commits.
Both of these options are obviously not particularly ergonomic to work with, and so &lt;code&gt;git&lt;&#x2F;code&gt; introduced the &lt;code&gt;--remote&lt;&#x2F;code&gt; flag to &lt;code&gt;git submodule update&lt;&#x2F;code&gt; to tell it to update to the branch tracked on the remote instead of the local repository.&lt;&#x2F;p&gt;
&lt;p&gt;Great, so now we know update our submodules to the latest remote commit (huzzah!), but I want to push to one repository and watch the other repositories automatically update to track that commit (instead of requiring me to run a command).
How can we do that?&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions to the rescue!
(although unfortunately it won&#x27;t quite get us all the way there)&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions allows you to trigger commands on arbitrary events using the &lt;a href=&quot;https:&#x2F;&#x2F;developer.github.com&#x2F;v3&#x2F;repos&#x2F;#create-a-repository-dispatch-event&quot;&gt;&lt;code&gt;repository_dispatch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; event.
The first step is to create a GitHub Action in our repository that updates submodules for us.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, the simplest way to do this would simply be to recursively clone the repository using GitHub&#x27;s &lt;code&gt;checkout&lt;&#x2F;code&gt; action, to run &lt;code&gt;git submodule update --remote&lt;&#x2F;code&gt; and then &lt;code&gt;git push&lt;&#x2F;code&gt; the changes back into the repository.
Unfortunately, this doesn&#x27;t quite work out for two reasons; we won&#x27;t have write access to the repository and we won&#x27;t be able to clone private repositories.
We can get around this by passing a &lt;a href=&quot;https:&#x2F;&#x2F;help.github.com&#x2F;articles&#x2F;creating-a-personal-access-token-for-the-command-line&quot;&gt;personal access token&lt;&#x2F;a&gt; to GitHub&#x27;s &lt;code&gt;checkout&lt;&#x2F;code&gt; action and telling it that we need to pull submodules recursively.
An example of this action can be found below, and is actually what I use in my site&#x27;s repo.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;Update module
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;repository_dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;types&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;update
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;update&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;runs-on&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;ubuntu-latest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;uses&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;actions&#x2F;checkout@v2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;${{ secrets.PAT }}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;submodules&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;recursive
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;Update module
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;          git submodule update --init --recursive --checkout -f --remote -- &amp;quot;${{github.event.client_payload.module}}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;          git config --global user.name &amp;quot;GitHub Action&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;          git config --global user.email &amp;quot;noreply@github.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;          git commit -am &amp;quot;deploy: ${{github.event.client_payload.module}} - ${{github.event.client_payload.sha}}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;          git push
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second step is to create the trigger for the &lt;code&gt;repository_dispatch&lt;&#x2F;code&gt; in the submodule repositories themselves.
This can be done using the excellent &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;peter-evans&#x2F;repository-dispatch&quot;&gt;repository-dispatch action&lt;&#x2F;a&gt; to send the event.
An example of this can be shown below.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;Dispatch to repo
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;workflow_dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;runs-on&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;ubuntu-latest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;strategy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;repo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;&amp;quot;owner&#x2F;repo&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;Push to repo
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;uses&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;peter-evans&#x2F;repository-dispatch@v1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;${{ secrets.PAT }}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;${{ matrix.repo }}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;event-type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;update
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;client-payload&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;&amp;#39;{&amp;quot;ref&amp;quot;: &amp;quot;${{ github.ref }}&amp;quot;, &amp;quot;sha&amp;quot;: &amp;quot;${{ github.sha }}&amp;quot;, &amp;quot;module&amp;quot;: &amp;quot;owner&#x2F;submodule&amp;quot;, &amp;quot;branch&amp;quot;: &amp;quot;master&amp;quot;}&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This of course works with submodules that you control, but what about for submodules that you don&#x27;t control?
Unfortunately there&#x27;s no way to start an action based on a push in a different repository, nor is there a way to create a webhook that you could use to trigger another action from a repository that you don&#x27;t control.
As such you are left with two options; to simply run the update action at a frequent interval or to hack together a way to do it with activity email notification and a &lt;code&gt;repository_dispatch&lt;&#x2F;code&gt;.
I know which of the two I&#x27;d rather implement in a hurry!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On the enjoyment of work</title>
        <published>2020-08-23T00:00:00+00:00</published>
        <updated>2020-08-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/work-enjoyment/"/>
        <id>https://tommoa.me/blog/work-enjoyment/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/work-enjoyment/">&lt;p&gt;I&#x27;m of the opinion that in society, the general attitude towards jobs is that you should &quot;do something that you&#x27;re passionate about&quot;.
If medicine takes your fancy, then take up your stethoscope and get to it.
Does the thought of court put you in a tizzy?
Find a briefcase and start practicing law.
Is graphic design your passion (yes)?
Then grab your wacom tablet and get ready to draw.&lt;&#x2F;p&gt;
&lt;p&gt;This is an attitude that gets taught to kids and is especially pushed throughout high school as teenagers get closer to the end of the secondary education and begin thinking about their adult life.
I remember being told to &quot;picture what I want to be doing in thirty years&quot; and to start taking steps towards doing that when I leave high school.
For me, I this was not exactly great advice - I had no clue what I wanted to pick between music or computer science!
Whilst I eventually decided on doing computer science, I definitely understand the reason why there&#x27;s so many people doing music, arts or history degrees - its what they&#x27;ve been told to do!
And if there was a high demand for professions in those areas, they would be able to spend their lives doing a job that they loved.
Unfortunately, given the number of people taking the courses and the general lack of capital-creating potential, its unrealistic that all of them would be able to get gainful employment, especially as the expected age of retirement seems to increase.
I don&#x27;t think that this is necessarily a point against doing the arts as a degree (again, I almost picked music, and my brother is actually studying French Horn), but I think that the wish to be entirely fulfilled by your full-time employment is both dangerous and misinformed.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve heard of engineering processes being like a four-sided piston several times - you need to have a balancing act between quality, cost, time and scope, and as each of them is moved, the others also need to be readjusted.
I think life is much the same way, there&#x27;s things that need balancing and we can&#x27;t have them all going at full steam.
I can&#x27;t be all in on my work and spending massive amounts of overtime whilst also trying to manage a family, stay in touch with older friends and keep a hobby.
It&#x27;s entirely unrealistic.&lt;&#x2F;p&gt;
&lt;p&gt;Most workplaces recognise this (or are forced to in Australia by the government) and have a maximum set of hours that you are paid to work - everything else is overtime.
So long as you aren&#x27;t taking an enormous amount of time to commute to work and aren&#x27;t continuing to work past your hours, that leaves roughly a third (or a quarter when factoring in eating) of the weekday - plus the weekend - to spend on things which &lt;em&gt;aren&#x27;t&lt;&#x2F;em&gt; work - family, friends and hobbies.
All of those are great things with which to be fulfilled.&lt;&#x2F;p&gt;
&lt;p&gt;My maternal Grandfather spent working years as a clinical biochemist.
He has long since retired and his &quot;hobby&quot; is now his employment; gardening.
He&#x27;s become so proficient at caring for plants and identifying native flora that he&#x27;s become an invaluable member of several parks in helping with botanical management.
Whilst I know that he enjoyed his time as a clinical biochemist, it was not his &quot;be all and end all&quot; to the point where it was where he gained his fulfilment from, instead he got fulfilment from his family, friends and hobbies.&lt;&#x2F;p&gt;
&lt;p&gt;This is much of the same approach that I&#x27;ve taken to music.
My gainful employment will be coming from software development, something that, yes, I enjoy, but that doesn&#x27;t mean that I&#x27;ll stop playing music.
Over the course of my time at university, I&#x27;ve continued my involvement in music, and by my own estimation am a significantly better musician now than I was then.
Whilst I am certain that the total improvement is likely not as great as if I had formally studied music, having music as a hobby that I enjoy and can gain fulfilment from without relying on it for my finances is both freeing and adds to my enjoyment of it.&lt;&#x2F;p&gt;
&lt;p&gt;I think that this is the right balance of things.
Even in jobs in which you would be theoretically fulfilled, you can still have things go wrong.
Sudden deadlines, a difficult workmate or an overbearing boss can all make jobs significantly less enjoyable.
If your previously fulfilling work is no longer enjoyable, then what are you enjoying?&lt;&#x2F;p&gt;
&lt;p&gt;Thus my charge to you is this; don&#x27;t put all your eggs in one basket.
In the end, work is work and should be approached as such.
It is a means to an end, to give you an opportunity to live the other parts of your life and shouldn&#x27;t be what your entire life is about.
So take up a hobby, spend more time with your family and friends, or start a job that you know you won&#x27;t enjoy but can use to further one of them.
I&#x27;d bet it&#x27;d make life more rewarding.&lt;&#x2F;p&gt;
&lt;p&gt;(disclaimer: author is an university student who hasn&#x27;t ever had to apply this advice in practice and is writing at about 1AM. Take it with ten grains of salt)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Imposter syndrome and improvement</title>
        <published>2020-08-22T00:00:00+00:00</published>
        <updated>2020-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/impostor-syndrome-and-improvement/"/>
        <id>https://tommoa.me/blog/impostor-syndrome-and-improvement/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/impostor-syndrome-and-improvement/">&lt;p&gt;I&#x27;ve recently been watching a lot of &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;user&#x2F;4Kddk&#x2F;&quot;&gt;Daniel Kapadia&#x27;s&lt;&#x2F;a&gt; (a.k.a. ddk) videos.
For those that don&#x27;t know, ddk is an ex-Quake professional, who&#x27;s moved into esports casting with a primary focus on FPS games.
In a (somewhat) &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YivCqfmcZGM?t=350&quot;&gt;recent video of his&lt;&#x2F;a&gt;, he says the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;...one limiting factor I had was - and I still suffer from this a great deal - and its part of the reason why, in some respects, I&#x27;ve achieved anything in some of the realms that I&#x27;ve worked in is impostor symdrome.
It&#x27;s been an issue for me.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s the thing that really makes me work really hard sometimes, but it also is the thing that makes me discount myself from feeling like I&#x27;m worth anything or good at what I do in any remote sense.
So that can be a really big issue for me, and it was an issue when I was a player...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This phrase reminded me of a rule from the &quot;Digital Age&quot; addition of Dale Carnegie&#x27;s &quot;How to Win Friends and Influence People&quot;; Give Others a Fine Reputation to Live Up To.
In many senses, I think that impostor syndrome is the other side of the coin for &quot;giving others a fine reputation to live up to&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The definition of impostor syndrome is to doubt your accomplishments or talents and to fear being exposed as a fraud.
If you are given a &quot;fine reputation to live up to&quot;, especially if its not for something that you&#x27;ve actually done yet (as &quot;How to Win Friends and Influence People in the Digital Age&quot; suggests), then of course you&#x27;ll have impostor syndrome.
You&#x27;re being expected to live up to some ideal which you haven&#x27;t achieved yet, and whilst being treated as though you&#x27;ve already achieved that ideal may be nice, you are - in the literal sense - an impostor.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;How to Win Friends and Influence People in the Digital Age&quot; suggests the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Coaches, mentors, leaders, and parents often find that people live up to our expectations of them, no matter how diminished those expectations are.
If a man feels unimportant or disrespected, he will have little motivation for improving himself.
So why not create a vision of him that embodies everything you know he is capable of achieving, as well as everything you don&#x27;t know about his possibilities?
You will rarely be disappointed...&lt;&#x2F;p&gt;
&lt;p&gt;To change somebody&#x27;s behaviour, change the level of respect she receives by giving her a fine reputation to live up to.
Act as though the trait you are trying to influence is already one of the person&#x27;s outstanding characteristics.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If this isn&#x27;t a call to the bettering influence of impostor syndrome, I don&#x27;t know what is!&lt;&#x2F;p&gt;
&lt;p&gt;We must also keep in mind the other component of the quote I&#x27;ve taken from ddk.
Impostor syndrome can cause people to &quot;discount themselves from feeling like they&#x27;re worth anything or good at what they do in any remote sense.&quot; - in other words, it can cause low self-esteem.
So there&#x27;s certainly some skill to the balancing act of trying to make people live up to the expectation of their better self without massively impacting self-esteem.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Honey, I shrunk the blog!</title>
        <published>2020-08-21T00:00:00+00:00</published>
        <updated>2020-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/shrinking-the-blog/"/>
        <id>https://tommoa.me/blog/shrinking-the-blog/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/shrinking-the-blog/">&lt;p&gt;At the time of writing this post, loading the front page of this blog without anything cached takes around 1MB of data.
Compared to the average website page (according to the &lt;a href=&quot;https:&#x2F;&#x2F;httparchive.org&#x2F;reports&#x2F;page-weight&quot;&gt;http archive&lt;&#x2F;a&gt;), this is actually pretty good.
The median page apparently ranks in at around 2MB of data, with about 1MB of that being images, and another half a megabyte of JavaScript.
Even worse, according to the http archive&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;almanac.httparchive.org&#x2F;en&#x2F;2019&#x2F;page-weight&quot;&gt;2019 page weight reports&lt;&#x2F;a&gt;, 10% of website pages are over 6MB, resulting in requiring &lt;em&gt;at least&lt;&#x2F;em&gt; a second to load the page on many internet connections around the world.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously this blog is no where near as bad, so why have I taken this entry to talk about page size and how I&#x27;ve made this blog smaller?
(Yes that&#x27;s the topic if you haven&#x27;t picked it up already.)
Well this blog is almost entirely text, with one image that is used for the header&#x2F;footer, and some custom fonts.
There is no JavaScript, no videos, some CSS (although not that much locally, only 9KB is CSS that is hosted here), so why on earth is this website checking in at even half of what the &quot;normal&quot; website would be?&lt;&#x2F;p&gt;
&lt;p&gt;Well the answer, as it turns out, is entirely that one image that is used for the header and footer of the website.
The profile image (which I use as my profile picture in most places) is a 2320x2314 JPEG image that takes up 747.8 KB of space.
That&#x27;s an absolutely whopping three quarters of my entire page, for one image that arguably isn&#x27;t even needed.
Fortunately, there&#x27;s ways around this.&lt;&#x2F;p&gt;
&lt;p&gt;The container that my image sits in at the top of my page is a square with a side length of 125 pixels, so this image only actually has to be 125x125 for there to be no noticable change in quality from the original.
The container at the bottom of the page is also a square with a side length of 30 pixel, and as 30 is not a divisor of 125 it makes sense to create an image for that separately so that the image doesn&#x27;t sub-sample oddly.&lt;&#x2F;p&gt;
&lt;p&gt;The static site generator that I use is called &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&quot;&gt;Zola&lt;&#x2F;a&gt;, and has a number of inbuilt functions in its templating.
One such function is the (very handy) &lt;code&gt;resize_image&lt;&#x2F;code&gt; function, which (as you&#x27;d expect) resizes an image to be of some particular dimensions.
The function processes an image for you and returns its path, allowing you to keep almost everything unchanged save the loaded image url.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-      &amp;lt;a href=&amp;quot;{{config.base_url}}&amp;quot; style=&amp;quot;background-image: url({{config.base_url}}&#x2F;img&#x2F;{{config.extra.profile}}&amp;quot;&amp;gt;&amp;lt;&#x2F;a&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;+      &amp;lt;a href=&amp;quot;{{config.base_url}}&amp;quot; style=&amp;quot;background-image: url({{resize_image(path=&amp;#39;..&#x2F;static&#x2F;img&#x2F;&amp;#39; ~ config.extra.profile, height=125, width=125, op=&amp;#39;fill&amp;#39;)}}&amp;quot;&amp;gt;&amp;lt;&#x2F;a&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By applying this function, I ended up with images of sizes 4.15KB and 1.21KB for the 125x125 and 30x30 images respectively, a total reduction of 742.4KB.
That&#x27;s basically a saving of the size of the entire original image, with no discernible change in image quality!&lt;&#x2F;p&gt;
&lt;p&gt;Of course, after this change I was greedy for more gains, and thus began my fight for fonts.&lt;&#x2F;p&gt;
&lt;p&gt;I use a number of fonts on this blog (and on my main website), which are generally downloaded from Google Fonts on demand via CSS.
Raleway is used for the text of front matter (the information for each blog post such as the publishing date, total words and tags), whilst the excellent Montserrat is used for the rest of the text elsewhere.
Whilst I have replaced my Raleway with a combination of &lt;a href=&quot;http:&#x2F;&#x2F;www.awayback.com&#x2F;index.php&#x2F;2010&#x2F;02&#x2F;03&#x2F;revised-font-stack&#x2F;&quot;&gt;Verdana and Geneva&lt;&#x2F;a&gt;, Montserrat will be sticking around as (in my opinion) one of the best looking variable weight sans-serif fonts available.
Thus, my savings with actual fonts was only around 20KB, relatively paltry gains.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; html, body {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     background-color: $background;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-    font-family: &amp;#39;Montserrat&amp;#39;, &amp;#39;Raleway&amp;#39;, sans-serif;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;+    font-family: &amp;#39;Montserrat&amp;#39;, &amp;#39;Verdana&amp;#39;, &amp;#39;Geneva&amp;#39;, sans-serif;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     font-weight: 400;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .frontmatter {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     color: $title;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     font-style: bold;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     list-style-type: none;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;     font-size: 14px;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-    font-weight: 700;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-    font-family: &amp;#39;Raleway&amp;#39;, sans-serif;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;+    font-weight: 500;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;+    font-family: &amp;#39;Verdana&amp;#39;, &amp;#39;Geneva&amp;#39;, sans-serif;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My major gains in the fonts department actually came from another place entirely... FontAwesome.
FontAwesome is a fantastic font for using company logos instead of images, which does indeed save a lot of data compared to the size that even one image of a logo would be.
The only problem is that the entire stack of FontAwesome icons that I&#x27;d need to get for my little symbols next to my website, GitHub and Atom feeds is around 130KB, which (now that we&#x27;ve shrunk a large portion of the website) accounts for about half of the remaining website.
Fortunately for me, FontAwesome provides SVGs of their icons, which allows me to download them all individually and use them instead in &lt;code&gt;&amp;lt;img&amp;gt;&lt;&#x2F;code&gt; tags.
The total size for the three icons individually is a little under 5KB, around 25 times smaller than the entire font.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;diff&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-diff &quot;&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;https:&#x2F;&#x2F;{{extra.website}}&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;website &amp;lt;i class=&amp;quot;fab fa-firefox&amp;quot; &amp;gt;&amp;lt;&#x2F;i&amp;gt;&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;li&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;+  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;https:&#x2F;&#x2F;{{extra.website}}&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;website &amp;lt;img class=&amp;quot;symbol&amp;quot; src=&amp;quot;&#x2F;symbols&#x2F;firefox-browser-brands.svg&amp;quot;&amp;gt;&amp;lt;&#x2F;img&amp;gt;&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;li&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;According to Firefox&#x27;s network tools, I&#x27;m now down to 128.2KB, of which my remaining font of Montserrat makes up a solid 70%, so there&#x27;s clearly still some room for improvement.
Perhaps I&#x27;ll continue to look for an alternative font to use instead.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The curious case of the disappearing ideas</title>
        <published>2020-08-20T00:00:00+00:00</published>
        <updated>2020-08-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/the-curious-case-of-the-disappearing-ideas/"/>
        <id>https://tommoa.me/blog/the-curious-case-of-the-disappearing-ideas/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/the-curious-case-of-the-disappearing-ideas/">&lt;p&gt;I&#x27;ve taken to setting aside time in evenings to write these entries (and very late in the evenings - its currently 11:40 PM).
This has mostly been fine in terms of my schedule.
I have university during the day, and I also often have other activities such as choir in the early evenings, so the late evening is pretty much the only time that I can write my entries without having it potentially disturbing the rest of my day.&lt;&#x2F;p&gt;
&lt;p&gt;But this has also lead to another thing which has arguably already negatively impacted this blog - I&#x27;ve forgotten almost every idea of what to write by the time I reach my allotted writing time.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes, I have a good idea in the middle of the day, or something to discuss that I&#x27;ve just done, and either of these would be a good idea to type up as an entry.
But by the time its the evening, after the vast majority of the day has gone and my focus begins to turn to the next day, I find it incredibly difficult to remember the details of my thoughts, the minutia of my activities or the ideas that came to me throughout the day.
Admittedly, this isn&#x27;t a particularly promising thing to admit at what is effectively the restarting of this blog, but in my opinion it is better that I am aware of this problem (especially as it would be likely to persist if never recognised) and am now able to think of methods to combat it.&lt;&#x2F;p&gt;
&lt;p&gt;One potential idea for me to do away with my structured day and instead to write whenever the ideas come to me.
This is somewhat tempting, because starting to put down ideas when they are fresh often means that the ideas will all be left semi-formed for me to come back to later to fill in.
I could quite easily see (however unlikely) my drafts folder reaching peak capacity, with too many half-formed (and likely duplicated) ideas left strewn around that I am left with the paralysis of too many choices.
The main reason why I wouldn&#x27;t necessarily want to do this approach, however, is because of the structure that I need for the rest of my life.
I&#x27;m currently in the final semester of my Masters, and as I &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;non-essay-word-count&#x2F;&quot;&gt;have previously mentioned&lt;&#x2F;a&gt;, I am in the process of writing my thesis.
Writing a thesis is a time consuming process, but I am also taking a full course-load in addition to my thesis, resulting in even more time being dedicated to university.
Thus, I require a large amount of rigid structuring of my day in order to ensure that I am able to get all the work of the semester done (and its arguable that I still don&#x27;t have enough structure to comfortably make it to the end of semester with full marks).&lt;&#x2F;p&gt;
&lt;p&gt;Another idea is to note down ideas in a journal of sorts, with none of the ideas as fleshed out as they would be (this is arguably just a variation on the above).
I already keep a small Moleskine journal on me to keep track of my tasks for the day, which has often proved invaluable in ensuring I don&#x27;t forget assessments.
Without modifying my day much, I could quite easily take short notes of my day and my ideas for this blog.
The disadvantage of this approach is simply that I would likely need to provide myself some context for each thought in order for my previous thoughts for each topic to be able to be recanted as I had originally thought.
Even of the topics I have already covered, if I had just written the title in my journal, I doubt that I would have been able to restate all of the points that I have.&lt;&#x2F;p&gt;
&lt;p&gt;Even as I struggle with this, I am lead to be incredibly impressed with the various YouTubers that I see uploading new content on a regular basis.
Whilst it is arguable that some topics practically write themselves (product reviews or political news come to mind), the variety work between those topics needs to be interesting for their existing audience to continue to want to watch it.
I think an example of this is LinusTechTips, who upload six videos a week on their main channel (and even more on their other channels).
Whilst the majority of their content is product reviews or based on technology news, in the last two weeks alone they&#x27;ve included videos about a Chinese x86 chip, a budget build from the jankiest origins, run a &quot;tech support&quot; challenge, done a video on the custom air conditioning in Linus&#x27; home, discussed a pyramid-shaped case that was requested and looked at the remaining players in the (arguably dead) sector of mp3 players.
That&#x27;s an incredibly wide range of topics, all of which appeal to their audience and all of which have an incredibly large number of views, but all entirely original content ideas.
That they have been able to keep up with the insane schedule of new videos, all whilst keeping fresh and original ideas coming over a matter of years is incredibly impressive to me.&lt;&#x2F;p&gt;
&lt;p&gt;I suppose I should hope that I can do the same.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The word count of essays that aren&#x27;t essays</title>
        <published>2020-08-19T00:00:00+00:00</published>
        <updated>2020-08-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/non-essay-word-count/"/>
        <id>https://tommoa.me/blog/non-essay-word-count/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/non-essay-word-count/">&lt;p&gt;As you (probably) know, I&#x27;ve just restarted this blog, and this is my fifth total entry.
One of my goals for this blog is to try to write one entry every day for as long as I can, with the purpose of creating a habit for me to keep.
My hope is that I am able to turn this blog into somewhat of a diary, a record of things that I&#x27;ve thought about and things that I&#x27;ve done, and as I continue to write, the time that is put aside for writing entries will allow me to think through and articulate ideas and concepts that I have throughout the day.&lt;&#x2F;p&gt;
&lt;p&gt;One of the interesting observations that I have already (especially considering that this is only the fifth day of doing this!) is that I&#x27;ve already written 3270 words (not including this entry) for this blog.
That&#x27;s almost as much as my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;masters-research&#x2F;proposal&#x2F;&quot;&gt;research proposal for my Masters&#x27; thesis&lt;&#x2F;a&gt; (which clocks in at 3429 words), and about half as many as my final thesis is expected to be.&lt;&#x2F;p&gt;
&lt;p&gt;3270 words in five days seems insane to me, especially considering that a good two-thirds of that was in the last two days alone, and none of these entries has taken me more than perhaps 45 minutes to write.
I&#x27;ve certainly never before had an easy time writing a lot of words, especially in one sitting - regardless of the topic.
My proposal took me close to four weeks to finish, and the complexity analysis that I wrote not long after took me nearly two weeks of straight writing (and I&#x27;m still editing it).
So what makes these so different?
I have a few theories.&lt;&#x2F;p&gt;
&lt;p&gt;For one, these essays are written with comparatively little research.
I certainly &lt;em&gt;have&lt;&#x2F;em&gt; done research for them (my entries on &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;contact-without-social-media&#x2F;&quot;&gt;contact without social media&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;esports-wont-be-mainstream&#x2F;&quot;&gt;esports probably never being mainstream&lt;&#x2F;a&gt; both had some rudimentary research done for them), but compared to a university essay?
It&#x27;s not even close.
The amount of time that I sank into researching my research proposal does indeed show, whilst I only have 15 references - which seems relatively paltry for a research paper - its proposal on a topic which I had no experience in.
Both papers on gravitational waves and the literature on refactoring are not usually part of my daily reading.
My unfamiliarity with the topics only exacerbates the issue of actually needing to read the papers.
One of my references in my research proposal is a 204 page PhD thesis, upon which my research builds.
Reading 204 pages takes enough time, but considering the mathematics and physics behind gravitational waves was not something I&#x27;d seen before, it took even longer for any of the content to actually make sense.
So certainly, the amount of research plays a role.&lt;&#x2F;p&gt;
&lt;p&gt;Another potentially contributing factor is the style of writing.
Most of my university essays are written in a very formal style, and it is important (at least to me) to be as concise as possible whilst wording any given sentence.
Why spend paragraphs trying to explain something that could be explained in a sentence?
(although sometimes you want to spend the paragraphs if the topic being explained may be obscure)
In contrast, the writing in the blog (so far) has been mostly prose.
I sit down in front of my computer with an idea, and I leave 45 minutes later with the equivalent of my thought pattern put into words.
My sentences and word choices aren&#x27;t as carefully chosen, and my tone is far more casual.
This means that the amount of time that it takes for me to construct any given sentence is scarcely more than the amount of time it takes me to think it, and although I do edit a little before publishing and do roughly plan the order of what will be said, my typing speed whilst writing these posts is almost always approaching full speed.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless of the reasons why (there may be even more that I haven&#x27;t immediately thought of), I do hope that some of the apparent efficiency with which I&#x27;ve been able to type these words can be translated to my university work.
I have a large number of essays due this semester, with each unit having on average at a little over one essay each and my thesis being due by the end of the semester.
If I could somehow take some of this speed to add to my more formal essays, the coming semester will be significantly easier.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Esports will probably never &quot;go mainstream&quot;</title>
        <published>2020-08-18T00:00:00+00:00</published>
        <updated>2020-08-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/esports-wont-be-mainstream/"/>
        <id>https://tommoa.me/blog/esports-wont-be-mainstream/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/esports-wont-be-mainstream/">&lt;p&gt;This is a topic that has sat on my heart for a very long time.&lt;&#x2F;p&gt;
&lt;p&gt;When I was in my first year of university (2016), the game Overwatch, by Activision Blizzard, was released.
As someone who plays a lot of games, mostly CounterStrike, and enjoyed playing Starcraft II whilst I was in high-school, I immediately hopped on board and played a &lt;em&gt;lot&lt;&#x2F;em&gt; of Overwatch.
When the Overwatch League was announced in November at Blizzcon 2016, I was very hyped.
Finally, esports would have a league that could go mainstream.
Teams would be based out of cities, giving the chance for lots of local fans to arrive.
There was a plan for creating a second and third tier leagues to make sure there was a space for new talent to develop and be discovered, and &lt;em&gt;finally&lt;&#x2F;em&gt; there would be a way to ensure that all the players had enough money to go full time.
And it seemed like a real possibility.&lt;&#x2F;p&gt;
&lt;p&gt;Both traditional sport and esport organisations clearly bought into the hype as well, with the Kraft Group and Stan Kroenke, as well as Cloud9 and Envy purchasing slots in the league for $20 million USD.
Top broadcast talent was moving into Overwatch as well, as Montecristo and Doa (previously best known for League of Legends commentary) and Semmler (from CounterStrike) jumped over to the Overwatch League.
The start of the first season of the Overwatch League in 2018 seemed to be a success as well, with enough viewers to rival CounterStrike&#x27;s majors, and plenty of exciting games to watch.
But everything seemed to come crashing down over the next few years.&lt;&#x2F;p&gt;
&lt;p&gt;The commissioner of the league, Nate Nanzer, &lt;a href=&quot;https:&#x2F;&#x2F;www.dexerto.com&#x2F;overwatch&#x2F;richard-lewis-an-analysis-nate-nanzer-leaving-overwatch-league-664386&quot;&gt;left Blizzard early into season 2&lt;&#x2F;a&gt;, leaving the league without its (arguably) most publicly-facing figure.
This was followed by a &lt;a href=&quot;https:&#x2F;&#x2F;www.dexerto.com&#x2F;overwatch&#x2F;behind-the-scenes-at-the-owl-esports-biggest-gamble-part-one-1309877&quot;&gt;large number of other Overwatch League staff leaving as well&lt;&#x2F;a&gt;, as well as a meta (short for &quot;meta-game&quot;) known as GOATS, which was so dull that player and viewing numbers dwindled.
There&#x27;s been a number of reports that &lt;a href=&quot;https:&#x2F;&#x2F;www.dexerto.com&#x2F;overwatch&#x2F;behind-the-scenes-at-the-owl-esports-biggest-gamble-part-two-1316988&quot;&gt;teams are all &quot;operating in the red&quot;&lt;&#x2F;a&gt;, and much of the broadcast talent that went to Overwatch &lt;a href=&quot;https:&#x2F;&#x2F;www.dexerto.com&#x2F;opinion&#x2F;losing-top-tier-talent-means-overwatch-league-is-in-trouble-1308240&quot;&gt;left at the start of season 3&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So what went so wrong?&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I went back to playing CounterStrike in mid-2018, and have barely looked back since.
There was a brief period in time where I played both Overwatch and CounterStrike at the same, but after the GOATS meta came into full force I lost almost all interest in playing.
I have, on occasion, tried to watch the Overwatch League since then, but have found it increasingly difficult as new characters and mechanics were introduced.
Sigma, Ashe, Baptiste and Echo were all introduced as characters in the short months after I stopped playing, and each time I was bewildered when I saw them.
How did their abilities work, what made them unique, how did they interplay with other characters?
The components of the game that I could only properly understand by playing were slowly falling away with each patch, and every time I tried to watch I&#x27;d find it difficult to tell what was going on.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve found that I have much of the same problem with League of Legends and DOTA, both of which I don&#x27;t play.
They both have a massive roster of characters (especially in relation to Overwatch), all with at least four unique abilities and interplay with other characters that cannot really be understood unless you have personal experience from playing.
In this sense, I can&#x27;t be amazed by some element of skill which I can&#x27;t even grasp.
Was this particular combination of abilities really hard to pull off in tandem?
I have no clue, I don&#x27;t play this game.
Was the interplay between these two characters such that someone who won really should have lost on paper?
I have no clue, I don&#x27;t play this game.
Was this particular tactic a mastermind choice that completely ruined any chance that the other team had to win?
I have no clue, I don&#x27;t play this game.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional sports don&#x27;t really have this problem - in comparison it&#x27;s easy to tell if something is difficult.
Watching a player in AFL jump over four other extremely muscular players to snatch a ball out of the air is impressive purely off of the fact that I am human, and I know that I&#x27;d have no chance.
Watching soccer players curl shots into the top corner of a goal is impressive purely based on it looking amazing and being a clearly difficult task.
Impressive saves in by goalkeepers boggle the mind with their quick reactions and fast movement, and I would (I think) be able to tell that even if I had never played a game of soccer in my life.
I wouldn&#x27;t be able to discuss tactics much without either playing myself or watching an inordinate number of games (much like esports), but the barrier to enjoyment and watching apparently spectacular plays is much, &lt;em&gt;much&lt;&#x2F;em&gt; lower.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, the ruleset by which interactions occur between players is much simpler in traditional sports.
I think that the simpleness of a ruleset can be modelled by how easy it to describe the objectives of the game.
Most traditional sports are, at their core, relatively simple: Do some objective more times than someone else.
Soccer - put the ball into the opponent&#x27;s goal more times than the other team without the ball touching your arms; Basketball - put the ball into the opponent&#x27;s hoop more times than the other team; NFL - run the ball into the opponent&#x27;s area more times than they do to you.
These simple end objectives may have some complicating factors - different point systems depending on where you shoot from for basketball or the offside rule in soccer - but even these are simple and intuitive.
Esports, on the other hand, is another beast entirely - try explaining how to win a game of League of Legends to someone without any context.
The lanes and towers and inhibitors before even getting to the base add a layer complexity which is only made worse by the Baron and Dragon (especially now that there are different Dragon types).
This is even further compounded by the skill system, the levels of the characters, the abilities and the concept of a &quot;build&quot;.
I can intuitively tell that destroying a tower in one of the lanes gets you closer to winning League, the reason behind Baron or any of the Dragons is a different matter entirely.&lt;&#x2F;p&gt;
&lt;p&gt;Even the (arguably) simplest esport, CounterStrike, suffers this problem to some extent.
It&#x27;s much more difficult to explain the roles of the Terrorists and Counter-terrorists and the &quot;phases&quot; of the game (pre-plant and post-plant) than it is to explain the basic premise of soccer, even though it is inherently impressive to watch someone land three one-deags, and easy to tell why winning a round with pistols against rifles is impressive.
Whilst it is easy to see the skill in CounterStrike, understanding goals of the game is much more difficult than in traditional sports.&lt;&#x2F;p&gt;
&lt;p&gt;This is a problem that is inherent in video games.
It is difficult to make massively replayable games without some form of guaranteed variation, which in video games comes from additional complexity to the goals of the game.
Would it be nearly as fun to play League of Legends if there were no items and a much smaller roster of characters?
For me, at least, the answer is no (although fans Heroes of the Storm might argue that the answer is yes).
Would it be as fun to play Overwatch if there were no abilities and no characters?
I certainly don&#x27;t think so, the difference and interplay between the different characters are part of the core reason why the game is fun.
The complexities of the interplay between characters and build selection is part of the reason why these games are so successful, even if it means to a casual audience that any high-level play is unintelligible.&lt;&#x2F;p&gt;
&lt;p&gt;And it&#x27;s to that casual audience that esports has to appeal if there&#x27;s any chance of esports &quot;going mainstream&quot;.
There will always be more people that don&#x27;t play a game than those that do play it, and it&#x27;s that audience that needs to be captured.
How many people do you know that watch some sport and follow their favourite team and yet hardly play that sport?
I&#x27;m a rabid Tottenham Hotspurs fan, and I haven&#x27;t played soccer for years, and there&#x27;s many others like me.
Of my friends who watch lots of sports, hardly any of them play the actual sport, instead the watching of a sport is a past time to enjoy with friends, whilst at a bar, or eating dinner.
It&#x27;s a break from real life, and can be followed from afar instead of requiring continual re-learning as new content is introduced.&lt;&#x2F;p&gt;
&lt;p&gt;To this end, I say that esports will never &quot;go mainstream&quot;.
The things that make the games fun are contrary to the things that make the games easy to watch casually, and if the game is easy to watch casually but not fun to play, no one will play it anyway.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>It&#x27;s hard to sync more than one machine</title>
        <published>2020-08-17T00:00:00+00:00</published>
        <updated>2020-08-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/multiple-machines-are-hard/"/>
        <id>https://tommoa.me/blog/multiple-machines-are-hard/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/multiple-machines-are-hard/">&lt;p&gt;I&#x27;ve long seen it reported that the sales of desktop machines is decreasing (although workstations are keeping steady or growing), whilst the sales of laptops, tablets (although almost entirely the iPad) and phones have shot through the roof.
Most of the reporting that I&#x27;ve seen has claimed that this is likely due to people not requiring more powerful machines for work or daily tasks - indeed most professions don&#x27;t require a powerful computer for most work, and with the ubiquity of high performance build servers, even some engineers and programmers don&#x27;t require the use of a powerful computer.&lt;&#x2F;p&gt;
&lt;p&gt;I think that this is probably part of the reason why, but there&#x27;s also a bit more to it.&lt;&#x2F;p&gt;
&lt;p&gt;It feels like almost everybody has some form of cloud-based storage these days.
From the previous standard-like Dropbox or Google Drive to the pre-installed iCloud or OneDrive, almost every person that I know has or uses some form of cloud storage - I even have three of them!
My university provides us OneDrive, which I use for storing university-related documents, I have a Google account, which I use for storing lots of personal documents, and I also use Google Photos for storing photos from my phone (and &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;contact-without-social-media&#x2F;&quot;&gt;good luck trying to tell me its the same as Google Drive&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;All of this feeds into one of the major gripes I have with any primarily cloud-based solution, such as the storage solutions above - synchronization is really &lt;em&gt;really&lt;&#x2F;em&gt; &lt;em&gt;&lt;strong&gt;really&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; hard.
I&#x27;ve definitely run out of fingers to count the number of times that I&#x27;ve tried to work locally on a synced document, only to later be told that it had caused a &quot;conflict&quot; with the document because I&#x27;d also tried editing it on another machine whilst I was somewhere else.
Countless hours have been spent manually figuring out which of the two or three versions was actually the right one and combining them in various ways, only to figure out days later that I&#x27;d chosen the wrong document to keep.&lt;&#x2F;p&gt;
&lt;p&gt;My quest (and probably everyone else&#x27;s quest as well) to try solve this issue has been long and storied.
I originally started out with a Dropbox account and a dream, before moving to Google Drive after I found out that it had an additional few gigabytes of free storage space.
After moving to Linux (and thus losing access to a native Google Drive client), I began using &lt;a href=&quot;https:&#x2F;&#x2F;syncthing.net&#x2F;&quot;&gt;Syncthing&lt;&#x2F;a&gt; to try to synchronize all my devices.
Unfortunately, none of these ever quite felt right to me whilst I was using both a desktop computer and a laptop, as I&#x27;d typically find that the synchronization time would be long enough that (if I&#x27;d done enough work recently or left a computer unsynchronized for a few weeks) I could make myself a cup of tea or coffee with time to spare.&lt;&#x2F;p&gt;
&lt;p&gt;This eventually pushed me to my current setup, which is to use &lt;code&gt;git&lt;&#x2F;code&gt; for files that I plan on keeping locally on any machines (with separate private repositories in GitHub for each area of my life) in addition to a Google Drive account that is for strictly online content.
Even this, I&#x27;ve found hard to maintain.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git&lt;&#x2F;code&gt; is fantastic at version control and making sure that multiple people are able to work on different parts of the same project at the same time, but its strength is certainly not in synchronization of documents.
Life using &lt;code&gt;git&lt;&#x2F;code&gt; has been made even more difficult of my own volition, by the fact that a large number of my private repositories automatically deploy to somewhere, such as this blog, or &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&quot;&gt;my main site&lt;&#x2F;a&gt; (even my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Tommoa&#x2F;ozgrav-research&quot;&gt;Masters&#x27; research&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;cv&#x2F;cv.pdf&quot;&gt;resume&lt;&#x2F;a&gt; are repositories that are automatically built and deployed).
This means that I typically want changes to be somewhat atomic, such that anybody else that sees them would be able to see a coherent document at any point on the commit tree.
This habit has copied over even into repositories that are entirely private (such as my repository for university), resulting in there usually being uncommitted changes at the end of the day, which I refuse to push simply because I don&#x27;t want to later have to force push.&lt;&#x2F;p&gt;
&lt;p&gt;This means that it is hard for me to do work across my multiple machines at the same time, and I can almost always guarantee that one of them is out of sync, especially as the number of repositories that I have grows.
The major result of this difficulty is that I&#x27;ve spent less and less time on all of my machines, and more and more of it on a single machine that I can do all my work on - my laptop.
After all, even if my desktop computer runs much faster, has a high refresh rate monitor attached and a significantly better keyboard, its far easier for me to just sit at a desk with my laptop and do work instead of trying to spend the time making sure that my desktop is entirely up-to-date - even if I am using &lt;code&gt;git&lt;&#x2F;code&gt; and Google Drive.
Further, the entire problem of synchronization is entirely masked if I only use one machine, as opposed to the Herculean effort that I&#x27;d need to put in otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;Now this leads us back to the my statement at the start of this entry that there&#x27;s more to the &quot;death&quot; of the desktop than the non-requirement of powerful hardware - why have I picked my laptop to do all my work on, especially considering my desktop is technically superior in every way?
The major reason for me is mobility.
Perth is largely out of the COVID-19 pandemic (we haven&#x27;t had a community infection since around May), and university has started up again, which means that I spend a significant proportion of my time at the university campus taking labs and workshops.
I simply can&#x27;t take my entire desktop setup with me (as much as I would love to), so I instead spend the majority of my day doing work on my laptop, and once I get home at the end of the day I don&#x27;t want to spend additional effort making sure that my desktop is up to date so I can do some work on it - and I imagine there&#x27;s a significant proportion of people in a similar position.
People are often expected to continue doing some form of work out of the office (although I can&#x27;t necessarily comment on the likelihood of this outside of the programming world, where you&#x27;re only really called in when something goes horribly wrong in my experience), and as such their single device needs to be portable and thus a laptop, tablet or phone.&lt;&#x2F;p&gt;
&lt;p&gt;So, why is the desktop dying?
Because of requirement of mobility and the difficulty of syncing more than one machine.&lt;&#x2F;p&gt;
&lt;p&gt;(This entry also basically lays out the reasoning for why I think that &quot;cloud storage&quot; such as Google Drive is actually closer to an automated backup system than a synchronization system)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Getting in contact without social media</title>
        <published>2020-08-16T00:00:00+00:00</published>
        <updated>2020-08-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/contact-without-social-media/"/>
        <id>https://tommoa.me/blog/contact-without-social-media/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/contact-without-social-media/">&lt;p&gt;Now that I&#x27;ve restarted (and somewhat revamped - I redid some of the templating) this blog, I&#x27;m left pondering a few things about how I set things up and what they actually mean for my own usage.&lt;&#x2F;p&gt;
&lt;p&gt;If you run the very excellent &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gorhill&#x2F;uMatrix&quot;&gt;uMatrix&lt;&#x2F;a&gt; or perhaps &lt;a href=&quot;https:&#x2F;&#x2F;noscript.net&quot;&gt;NoScript&lt;&#x2F;a&gt; in order to prevent JavaScript or media from running without your knowledge, you will have noticed that I have (at the time of writing this) no JavaScript running at all.
There&#x27;s a fair bit of CSS (mostly fonts and symbols), but nowhere is there any JavaScript.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing which you may (if you&#x27;re particularly nosy) have noticed is that this blog is hosted on &lt;a href=&quot;https:&#x2F;&#x2F;pages.github.com&#x2F;&quot;&gt;GitHub Pages&lt;&#x2F;a&gt;.
This is great in that I am able to very easily make changes without having to worry too much about deployment (I just write a markdown file and call it a day) as well as in that everything is in source control, but also not great in two very specific ways.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The first of these is that I have no clue how many people will&#x2F;would&#x2F;are visiting the blog (or indeed my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&quot;&gt;main site&lt;&#x2F;a&gt;), with very few options as to how to find it out.
One option would be to do the old trick that is used for determining if someone has opened an email -- include an image or css file that is actually a webhook and just increases a counter.
This would actually be achievable using &lt;a href=&quot;https:&#x2F;&#x2F;ifttt.com&#x2F;&quot;&gt;IFTTT&lt;&#x2F;a&gt; and a its &quot;Webhook&quot; connection, and is possibly a project for another day.
Another option would be to introduce something like Google&#x27;s Analytics (&lt;em&gt;shiver&lt;&#x2F;em&gt;) to track people as they visit.
I&#x27;m loathe to voluntarily subject people to more tracking by my own volition, so arguably that&#x27;s out of the question.&lt;&#x2F;p&gt;
&lt;p&gt;The second problem that I have is that there&#x27;s no method for interactivity - by which I mean comments.
How can I get feedback on topics on a site in which I have the only ability to add anything and there&#x27;s no contact details?
Blogs like &lt;a href=&quot;https:&#x2F;&#x2F;utcc.utoronto.ca&#x2F;~cks&#x2F;space&#x2F;blog&quot;&gt;Chris Siebenmann&#x27;s&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;nullprogram.com&quot;&gt;Chris Wellons&#x27;&lt;&#x2F;a&gt; have easy methods for feedback, and regularly include responses to comments on previous topics as new entries.
An easy methodology to contact me would also mean that if I should get anything wrong or have issues with understanding some topic, it would be easy for any readers to immediately correct me using that contact method.
This problem is a little more complex than the previous in that I both have methods to solving it and do not wish to use those methods, which is further compounded by the fact that there is &lt;em&gt;no&lt;&#x2F;em&gt; way to get in contact to give me additional suggestions that I might use instead.&lt;&#x2F;p&gt;
&lt;p&gt;One potential solution is to include an email address somewhere for people to send mail to.
My issue with this solution is threefold.
First, I don&#x27;t know what provider I should put any new mail on, or indeed what the email address should be.
It would be possible to set up a Gmail (or equivalent) account, but I already have what feels like far too many Google accounts.
I could potentially use&#x2F;pay for mail hosting from a service provider and use this domain to receive email, however that runs into the issue of needing to &lt;em&gt;pay&lt;&#x2F;em&gt;, which the frugal university student in me cannot allow.
Second, I like staying on top of all my email.
I&#x27;ve seen many people with thousands of unread emails, and even the thought of such a scenario occurring fills me with dread.
As this blog (hopefully) becomes more popular, then equally so the amount of engagement would continue, and my paltry attempts to stay on top of all my emails and reply to all those that need replying to become much more difficult.&lt;&#x2F;p&gt;
&lt;p&gt;Another potential solution to this problem would be to direct people to something like Twitter or Facebook, of which Twitter is arguably the better choice for quick feedback.
I do indeed have a Twitter account that has sat dormant for as many days as I have had it, and I firmly intend to keep it that way.
I&#x27;ve seen Twitter and other social media accounts take over people&#x27;s lives to such a degree that I&#x27;m not enthused about dipping my toes in more than I need to (even though this self-imposed limitation probably means that this blog is highly unlikely to ever grow).
Similarly, whilst I do have a Facebook account (which could probably be found with some rudimentary searching), I don&#x27;t see messages from people that I&#x27;m not friends with, and I don&#x27;t add people as friends on Facebook (or LinkedIn for that matter) that I haven&#x27;t met in some capacity.
All of this means that to me, at the very least, there&#x27;s very little opportunity for interaction on any social media platform.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps there are other solutions that I haven&#x27;t thought of to these problems, but unfortunately, at least for the time being there is no way of getting any of those solutions to me.
Ah well, a problem for future me to deal with at some point.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Starting this blog again</title>
        <published>2020-08-15T00:00:00+00:00</published>
        <updated>2020-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/a-new-start/"/>
        <id>https://tommoa.me/blog/a-new-start/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/a-new-start/">&lt;p&gt;It&#x27;s been some time since I&#x27;ve actually updated my blog.
Despite trying several times to write more content, the last post I published was from &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;blog&#x2F;poly&quot;&gt;mid-2018, and was written as a 30 minutes commentary on some code that I wrote&lt;&#x2F;a&gt;, so clearly it hasn&#x27;t been working too well for me.&lt;&#x2F;p&gt;
&lt;p&gt;But things will be (hopefully) changing today.
I&#x27;m going to stop trying to write fully-formed content and ideas on my &quot;blog&quot; (which to be honest, no-one actually reads, or at least I don&#x27;t have any stats on it), and instead start trying to write daily updates on things that I&#x27;m doing.
Instead, my &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&quot;&gt;main site&lt;&#x2F;a&gt; will be for fully formed ideas.&lt;&#x2F;p&gt;
&lt;p&gt;By necessity, this means that my blog will not be entirely tech-focussed as I had intended many years ago, and instead will just be simply whatever I feel like talking about.
This may mean that this blog could turn into (basically) the equivalent of a Twitter account for me, with random daily thoughts and ideas popping in and out, or it may become a platform for me to practice a more casual style of writing after having written many formal papers throughout university.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, please do wish me luck as I try to embark on this journey.
I look forward to seeing where (if anywhere) this goes!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>OzGrav 2020 Research Proposal</title>
        <published>2020-04-20T00:00:00+00:00</published>
        <updated>2020-04-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/masters-research/proposal/"/>
        <id>https://tommoa.me/masters-research/proposal/</id>
        
        <content type="html" xml:base="https://tommoa.me/masters-research/proposal/">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;In 1687, Isaac Newton published his book, “&lt;em&gt;Philosophiæ Naturalis
Principia Mathematica&lt;&#x2F;em&gt;”, containing his law of universal gravitation:&lt;&#x2F;p&gt;
&lt;p&gt;\[F = G\dfrac{m_1m_2}{r^2},\]&lt;br &#x2F;&gt;
where \(F\) is the resultant gravitational force, \(G\) is the universal
gravitational constant, \(m\) is the mass of the objects and \(r\) is
the distance between the objects.&lt;&#x2F;p&gt;
&lt;p&gt;It has since been taught in high-schools across the world in
introductory physics classes, due in part to its simplicity and general
accuracy for predicting movement. Despite its general applicability, one
major issue of the theory is that it infers that gravitational is
instantaneously applied, without any apparent method through which it
could be transmitted.&lt;&#x2F;p&gt;
&lt;p&gt;Roughly two centuries later, in 1905, Albert Einstein presented the
theory of special relativity in his paper “&lt;em&gt;Zur Elektrodynamik bewegter
K&lt;span&gt;ö&lt;&#x2F;span&gt;rper&lt;&#x2F;em&gt;” (English: &lt;em&gt;“On the Electrodynamics of Moving
Bodies”&lt;&#x2F;em&gt;). The theory introduced the concept of &lt;strong&gt;spacetime&lt;&#x2F;strong&gt; to
describe inertial reference frames as a four-dimensional coordinate
system, \((t, x, y, z)\), where \(t\) is time and \((x, y, z)\) are the
three spatial dimensions. He further stated two important axioms; that
the speed of light in a vacuum is the same for all observers regardless
of motion and that the laws of physics are invariant in all inertial
frames of reference. About ten years later, Albert Einstein incorporated
the effect of gravity with special relativity, forming the general
theory of relativity.&lt;&#x2F;p&gt;
&lt;p&gt;The general theory of relativity postulates that the effect of gravity
can be characterised as each gravitational potential source changing the
curvature of spacetime. The relationship of gravitational mass-energy
and the shape of spacetime is given by Einstein’s field equations:&lt;&#x2F;p&gt;
&lt;p&gt;\[G_{\mu{}v} + \Lambda{}g_{\mu{}v} = \dfrac{8\pi{}G}{c^4}T_{\mu{}v},\]&lt;br &#x2F;&gt;
where \(T_{\mu{}v}\) is the stress-energy tensor&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, \(G_{\mu{}v}\) is
the Einstein tensor, \(g_{\mu{}v}\) is the spacetime metric, \(\Lambda\)
is the cosmological constant, \(G\) is the universal gravitational
constant and \(c\) is the speed of light.&lt;&#x2F;p&gt;
&lt;p&gt;An implication of gravity curving spacetime is that massive accelerating
objects would cause ‘ripples’ in fabric of spacetime called
gravitational waves. The existence of gravitational waves remained a
theory until 1974, when Russell Hulse and Joseph Taylor discovered a
binary pair of neutron stars that were orbiting each other. After
several years of measurement, they found that the speed at which the
stars were orbiting each other was slowing in a manner consistent with
the predictions of the general theory of relativity, showing that
gravitational waves did indeed exist &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#15&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There were several experiments performed in the 1960s and 1970s to
determine methods to detect gravitaional waves, resulting in several
large laser interferometric detectors (that is, detectors that use
interferometry the phenomena by which waves superpose on each other to
create a resultant wave for detection) being built throughout the early
2000s, including the American Laser Interferometric Gravitational-Wave
Observatory (LIGO) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, the Italian Virgo detector &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#14&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and the German GEO600 detector. The
initial observation runs between 2002 and 2011 by the various detectors
failed to directly detect any gravitational waves, and as such, the
majority of the detectors began work to increase their sensitivity
throughout the 2010s &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The increase in detector
sensitivity has brought success in the search for gravitational waves,
with the first direct detection occurring on the 14th of September, 2015
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Due to their design, the detectors have a significant amount of noise
from sources that are not gravitational waves, in addition to the
gravitational waves themselves having very weak signals. As such, a
large amount of data processing needs to be done to the outputs produced
by the detectors in order to filter and extract any possible
gravitational waves. These data processors are known as ‘&lt;em&gt;pipelines&lt;&#x2F;em&gt;’,
and are mostly created by research groups that are a part of the LIGO
Scientific Collaboration &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#11&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. These
pipelines are used throughout observation runs for real-time data
analysis.&lt;&#x2F;p&gt;
&lt;p&gt;One such pipeline is the Summed Parallel Infinite Impulse Response
(SPIIR) pipeline, created by Shaun Hooper in 2012 &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
The pipeline uses a number of IIR filters which are commonly used in
signal processing for bandpass filtering to approximate possible
gravitational wave signals for detection. The pipeline was further
developed by Qi Chu in 2017, by using GPU acceleration techniques to
increase the speed of analysis, as well implementing a method to use a
frequentist coherent search &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The pipeline is currently the
fastest of all existing pipelines, and has participated in every
observation run since November 2015, successfully detecting all events
that were seen in more than one detector.&lt;&#x2F;p&gt;
&lt;p&gt;The SPIIR pipeline uses GStreamer, a library for composing, filtering
and moving around signals, in addition to the GStreamer LIGO Algorithm
Library (&lt;code&gt;gstlal&lt;&#x2F;code&gt;). After receiving data from the detectors, the
pipeline performs data conditioning and data whitening, followed by the
usage of the IIR filters. The data is then combined for post-processing,
where events are given sky localization and then inserted into the LIGO
event database &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problem-description-goal&quot;&gt;Problem Description &amp;amp; Goal&lt;&#x2F;h2&gt;
&lt;p&gt;As of 2020-04-20, the SPIIR pipeline supports the use of two or three detectors for
gravitational wave searching the two American LIGO detectors and the
Virgo detector. There are several issues with the current pipeline
design that this research project aims to address.&lt;&#x2F;p&gt;
&lt;p&gt;Further detectors are likely to be coming online in the near future,
with old detectors occasionally being removed from detection for
maintainance. For example, the Japanese KAGRA detector is undergoing
testing with the goal of being used in the next observation run, and
LIGO India is currently being installed. With the current design of the
pipeline, adding and removing detectors is a significant undertaking
that takes a substantial amount of development time.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, if a detector is indeed added to SPIIR, the detector
&lt;em&gt;&lt;strong&gt;must&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; be used for the coherent post-processing, and can’t be used
just for synchronization purposes. This presents an issue as additional
detectors are added, as each detector has its own sensitivity, reading
variations and range of observable gravitational wave frequencies,
resulting in some detectors being suitable for searching specific
frequency ranges whilst showing no discernable change in output for
other detectors, causing many false negatives.&lt;&#x2F;p&gt;
&lt;p&gt;An ideal architecture for the pipeline would be significantly more
composable, able to add and remove the usage of different detectors for
post-processing with minimal effort.&lt;br &#x2F;&gt;
As such, this research project aims to complete a subsection of this
idealised architecture. The project aims to remove the requirement for
all detectors to be used for coherent post-processing with sky
localization, and instead aims to provide a generic interface that would
allow for any number of detectors to be used for coherent
post-processing, whilst still allowing the unused detectors to undergo
all other parts of the pipeline and remain synchronized with the used
detectors. The project shall explore a number of different possible
codebase refactorings as well as exploring new techniques for
efficiently combining \(N\) data sources for coherent search, and shall
measure the performance impact of the changes using a number of
benchmarks.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;literature-review&quot;&gt;Literature Review&lt;&#x2F;h1&gt;
&lt;p&gt;This research project aims to refactor the SPIIR pipeline codebase and
explore techniques for combining some unknown \(N\) number of data
sources for coherent search. Whilst the refactoring part of the project
is somewhat tangential to the aims of the project, looking at the
literature for refactoring will help with the development of the
research methodology. The literature for both refactoring and coherent
search are developing and varied.&lt;br &#x2F;&gt;
Refactoring is defined by Murphy-Hill as the
process of changing the structure of software without changing its
behaviour &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#12&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Of course, this isn’t the only way to modify source code to
address known issues. George Fairbanks offers the options of ignoring,
refactoring or rewriting code as potential methods to deal with problems
in (Fairbanks 2019), and makes several distinctions between the options.
According to Fairbanks, the major difference between refactoring and
rewriting is the process by which the code is modified. When
refactoring, incremental changes are made to the odebase, with the major
goal being to keep the newly written code integrated with the existing
codebase and tests, as the outputs of a module given some inputs should
still remain identical. In contrast, when rewriting, the new code is
written using none of the existing codebase, possibly resulting in
majorly different outputs and possibly even data flow architecture.
Unlike with refactoring, existing tests might not be able to be
leveraged, but it becomes much easier to make sweeping architectural
changes to the codebase.&lt;&#x2F;p&gt;
&lt;p&gt;This still leaves the third option ignoring the issues. Fairbanks points
out that ignoring issues simply means that they will have to be dealt
with at a later date, and contribute to ‘&lt;em&gt;techinical debt&lt;&#x2F;em&gt;’ a term
coined by Ward Cunningham in (Cunningham 1992) to help explain why
otherwise working code may need to be refactored or rewritten, and has
since turned into its own area of academic research, as well as a major
focus of industry. Some examples of activities that “accrue” technical
debt are; a lack of documentation, implementing sub-optimal algorithms
and a lack of testing. Allman notes that technical debt has a
number of similarities to financial debt, in that there can be advantages
and disadvantages to accruing the debt &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. One such advantage, is that
the codebase can be shipped without being entirely complete, and
may indeed reach functional completeness in a shorter time than if the
technical debt was not accrued. Some potential disadvantages, however,
include faults in the system, increased maintainance and extensibility
effort, as well as increased time onboarding new members of staff.&lt;&#x2F;p&gt;
&lt;p&gt;Technical debt, then, is clearly an area that needs to be managed over
the course of a programming project, even when rewriting or refactoring.
(Fairley and Willshire 2017) notes that whilst rewriting or reworking an
existing codebase can reduce or eliminate technical debt, the project
also risks accumulating additional debt if not correctly managed. To
help with management, (Fairley and Willshire 2017) suggests adopting a
development process that includes regularly reviewing expected and
actual progress, whilst Allman encourages regular internal and
external documentation, as well as maintaining an index of prioritised
debts &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
The SPIIR pipeline uses a group of IIR (infinite impulse response)
filters with time delays to approximate a matched filter. Xiaoyang Guo states
in a 2018 paper that the output of the (i)th IIR filter can be expressed
with the equation:&lt;&#x2F;p&gt;
&lt;p&gt;\[y^i_k = a^i_1y^i_{k-1} + b^i_0x_{k-d_i},\]&lt;br &#x2F;&gt;
where \(a^i_1\) and \(b^i_0\) are coefficients, \(k\) is time in a
discrete form and \(x_{k-d_i}\) denotes input with some time delay
\(d_i\) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. After summing the output of the filters, the resulting signal
undergoes coherent post-processing to determine the likelihood of an
event having occurred.&lt;&#x2F;p&gt;
&lt;p&gt;Coherent post-processing was introducted in Qi Chu&#x27;s thesis as an alternative
to coincidence post-processing&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Qi Chu states that the
multi-detector maximum log likelihood ratio to be equal to the coherent
signal to noise ratio \(\rho{}^2_c\), which can be expressed as:&lt;&#x2F;p&gt;
&lt;p&gt;\[\rho^2_c = \underset{max{A_{jk},\theta,t_{c},\alpha,\delta}}{\ln \mathcal{L}_{NW}},\]&lt;br &#x2F;&gt;
where \(A_{jk}\) describes the relative inclination of the detector to
the source, \(\theta\) is the mass of the source, \(\alpha\) and
\(\beta\) are the sky directions of the source and \(\mathcal{L}_{NW}\)
is the network log likelihood network.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst SPIIR’s coherent search currently only supports the use of two or
three detectors, Qi Chu estimates the computational cost of the
coherent search to be:&lt;&#x2F;p&gt;
&lt;p&gt;\[O(2N^3_dN_mN_p),\]&lt;br &#x2F;&gt;
where \(N_d\) is the number of detectors, \(N_m\) is the number of sets
of IIR filters, and \(N_p\) is the number of sky locations&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Xiaoyang Guo
discusses a number of optimizations made to the pipeline,
including in sections of the coherent post-processing, but only reduced
constant factors and not the computational cost of the overall process &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
As such, as more detectors are introduced, the computational time for
coherent search increases cubically.&lt;&#x2F;p&gt;
&lt;p&gt;An interesting parallel can, however, be made to sorting, a very widely
studied area of computer science. Comparison sorts are known to have a
lower bound of \(\Omega{}(n\log{n})\) number of comparison operations
(Cormen et al., n.d.) which can be increased depending on the
algorithmic inputs, however when implemented on a distributed network,
the number of comparators per thread can be reduced to \(O(\log^2{n})\)
using a sorting network, which uses a fixed set of comparisons on the
order of \(O(n\log^2{n})\) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. By measuring the total number of
comparitors, it would appear that the distributed algorithm is less efficient,
however GPUGems (&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) notes that the distributed algorithm can sort more keys
per second than an optimal \(O(n\log{n})\) algorithm running on a single
thread.&lt;&#x2F;p&gt;
&lt;p&gt;The SPIIR coherent search is distributed on a number of GPUs using CUDA
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, however the computational cost in Qi Chu&#x27;s thesis is
computed as being on the order of the number of computations, not the
number of computation per thread &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It is therefore possible that the
computational cost per thread is different to the overall computational
cost, and thus as detectors are added using the existing algorithm, the
growth of the computational runtime may not be cubic.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sec:method&quot;&gt;Methods&lt;&#x2F;h1&gt;
&lt;p&gt;The process for development will follow the suggested method in (Fairley
and Willshire 2017) to minimize technical debt. The gravitational wave
research group at the University of Western Australia meets once a week
to present progress reports and submit the planned progress for the next
week. By tracking the difference between planned progress and the actual
progress each week, the level of technical debt that the project is
incurring can be roughly determined. Another method by which technical
debt can be minimized is through correct testing&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Unit
tests will be created for the coherent search function to determine the
correct outputs using the existing algorithm, and as components are
refactored, the tests will be used to ensure that there are no
regressions. Internal and external documentation shall also be created
and maintained throughout the project as per Allman&#x27;s paper&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, with
internal documentation being comments on the function of code, and
external documentation being the methods stated in the final report.&lt;&#x2F;p&gt;
&lt;p&gt;Development for the new pipeline will be performed on the OzStar cluster
at Swinburne University of Technology &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#13&quot;&gt;15&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The OzStar cluster already
contains a set of sample data to run the pipeline on, as well as the
tools for running the pipeline. As such, all testing will be performed
on the cluster using the existing sample data.&lt;&#x2F;p&gt;
&lt;p&gt;Validation of the correctness of the eventual coherent search algorithm
will be an important factor to show that there are no behavioural
regressions in the course of the project. Validation will be performed
using a copy of the existing codebase and comparing the outputs of the
coherent search function for equivalent inputs. If the new algorithm
raises any false positives or false negatives that were not also seen in
the existing codebase, then it can be stated that the new algorithm is
not correct.&lt;&#x2F;p&gt;
&lt;p&gt;This project will also measure the performance and computational cost
difference between the 2-3 detector specific coherent search function
and the generalised coherent search function. The difference in
computational cost will be measured by an analysis of the average case
of the resulting algorithm and comparing it to the average case of the
original coherent search function. The performance cost will be measured
by determining the runtime of coherent search and comparing it across
equivalent inputs for different sized inputs.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;expected-findings&quot;&gt;Expected Findings&lt;&#x2F;h1&gt;
&lt;p&gt;There are a number of expected findings from this research. First, it
would be expected that the new coherent search algorithm would replicate
the outputs of the existing search algorithm for the same inputs (i.e.
it is valid as per section &lt;a href=&quot;https:&#x2F;&#x2F;tommoa.me&#x2F;masters-research&#x2F;proposal&#x2F;#sec:method&quot;&gt;3&lt;&#x2F;a&gt;). Second, it is expected
that no new coherent search algorithm is found, and that the
generalisation of the existing algorithm results in a regression of less
than 5% of the current coherent search runtime.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;proposed-timeline&quot;&gt;Proposed timeline&lt;&#x2F;h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;th style=&quot;text-align: left;&quot;&gt;&lt;span&gt; &lt;strong&gt;Task&lt;&#x2F;strong&gt; &lt;&#x2F;span&gt;&lt;&#x2F;th&gt;
&lt;th style=&quot;text-align: left;&quot;&gt;&lt;span&gt; &lt;strong&gt;Time&lt;&#x2F;strong&gt; &lt;&#x2F;span&gt;&lt;&#x2F;th&gt;
&lt;th style=&quot;text-align: left;&quot;&gt;&lt;span&gt; &lt;strong&gt;Description&lt;&#x2F;strong&gt; &lt;&#x2F;span&gt;&lt;&#x2F;th&gt;
&lt;&#x2F;thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Proposal Writing (Due 2020-04-20)&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-03 to 2020-04&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Write research proposal.&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Literature Review&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-04 to 2020-06&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Investigate efficient coherent search methods&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Analyse Existing Codebase&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-04 to 2020-07&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Determine expected inputs and outputs of coherent search methods and determine per-thread computational cost&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Determine valid unit tests&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-05&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Determine tests that can be used to determine the correctness of coherent search algorithms&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Oral Progress Report (Due 2020-05-22)&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-05&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Give report detailing progress on research&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Refactor Existing Codebase&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-06 to 2020-08&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Perform changes on pipeline&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Validate New Pipeline&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-08&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Compare outputs from changed pipeline to the previous version to ensure there is not a regression of results&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Measure Performance Differences&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-08&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Determine performance cost of changes&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Abstract&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-08 to 2020-09&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Prepare and submit research abstract&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Seminar&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-09 to 2020-10&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Prepare and give seminar on research&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Paper Writing&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;2020-09 to 2020-10&lt;&#x2F;td&gt;
&lt;td style=&quot;text-align: left;&quot;&gt;Prepare and submit paper on research&lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Tensors are very similar to matrices of vectors and are typically
used to describe mathematical geometric relationships&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Abbott, B. P., R. Abbott, T. D. Abbott, M. R. Abernathy, F. Acernese, K.
Ackley, C. Adams, et al. 2016. “Observation of Gravitational Waves from
a Binary Black Hole Merger.” &lt;em&gt;Phys. Rev. Lett.&lt;&#x2F;em&gt; 116 (6): 061102.
&lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1103&#x2F;PhysRevLett.116.061102&quot;&gt;https:&#x2F;&#x2F;doi.org&#x2F;10.1103&#x2F;PhysRevLett.116.061102&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;“About ‘aLIGO’.” n.d. &lt;em&gt;LIGO Lab: Caltech&lt;&#x2F;em&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;page&#x2F;about-aligo&quot;&gt;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;page&#x2F;about-aligo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Allman, Eric. 2012. “Managing Technical Debt.” &lt;em&gt;Commun. ACM&lt;&#x2F;em&gt; 55 (5):
50–55. &lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1145&#x2F;2160718.2160733&quot;&gt;https:&#x2F;&#x2F;doi.org&#x2F;10.1145&#x2F;2160718.2160733&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;13&lt;&#x2F;sup&gt;
&lt;p&gt;Chu, Q. 2017. “Low-Latency Detection and Localization of Gravitational
Waves from Compact Binary Coalescences.”&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;14&lt;&#x2F;sup&gt;
&lt;p&gt;“GPUGems Chapter 46. Improved Gpu Sorting.” n.d. &lt;em&gt;NVIDIA Developer&lt;&#x2F;em&gt;.
NVIDIA.  &lt;a href=&quot;https:&#x2F;&#x2F;developer.nvidia.com&#x2F;gpugems&#x2F;GPUGems2&#x2F;gpugems2_chapter46.html&quot;&gt;https:&#x2F;&#x2F;developer.nvidia.com&#x2F;gpugems&#x2F;GPUGems2&#x2F;gpugems2_chapter46.html&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;Guo, Xiaoyang, Qi Chu, Zhihui Du, and Linqing Went. 2018. “GPU-Optimised
Low-Latency Online Search for Gravitational Waves from Binary
Coalescences.” In, 2018-:2638–42. EURASIP.
&lt;a href=&quot;https:&#x2F;&#x2F;ieeexplore.ieee.org&#x2F;document&#x2F;8553574&quot;&gt;https:&#x2F;&#x2F;ieeexplore.ieee.org&#x2F;document&#x2F;8553574&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;Hooper, Shaun, Shin Kee Chung, Jing Luan, David Blair, Yanbei Chen, and
Linqing Wen. 2012. “Summed Parallel Infinite Impulse Response Filters
for Low-Latency Detection of Chirping Gravitational Waves.” &lt;em&gt;Physical
Review D - Particles, Fields, Gravitation and Cosmology&lt;&#x2F;em&gt; 86 (2).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;“LIGO Detected Gravitational Waves from Black Holes.” n.d. &lt;em&gt;Caltech&lt;&#x2F;em&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;detection&quot;&gt;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;detection&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;“LIGO Lab: Caltech: MIT.” n.d. &lt;em&gt;Caltech&lt;&#x2F;em&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.ligo.caltech.edu&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;11&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;“LIGO Scientific Collaboration.” n.d. &lt;em&gt;LIGO Scientific Collaboration&lt;&#x2F;em&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;ligo.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;ligo.org&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;12&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;Murphy-Hill, E, C Parnin, and A. P Black. 2012. “How We Refactor, and
How We Know It.” &lt;em&gt;IEEE Transactions on Software Engineering&lt;&#x2F;em&gt; 38 (1):
5–18. &lt;a href=&quot;https:&#x2F;&#x2F;ieeexplore.ieee.org&#x2F;document&#x2F;6112738&quot;&gt;https:&#x2F;&#x2F;ieeexplore.ieee.org&#x2F;document&#x2F;6112738&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;13&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;15&lt;&#x2F;sup&gt;
&lt;p&gt;“OzStar – Supercomputing at Swinburne University of Technology.” n.d.
&lt;em&gt;Swinburne University of Technology&lt;&#x2F;em&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;supercomputing.swin.edu.au&#x2F;&quot;&gt;https:&#x2F;&#x2F;supercomputing.swin.edu.au&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;14&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;“Virgo Detector.” n.d. &lt;em&gt;Virgo&lt;&#x2F;em&gt;. &lt;a href=&quot;http:&#x2F;&#x2F;www.virgo.infn.it&#x2F;&quot;&gt;http:&#x2F;&#x2F;www.virgo.infn.it&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;15&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Weisberg, Joel M., Joseph H. Taylor, and Lee A. Fowler. 1981.
“Gravitational Waves from an Orbiting Pulsar” 245 (4): 74–83.
&lt;a href=&quot;https:&#x2F;&#x2F;www.jstor.org&#x2F;stable&#x2F;24964580&quot;&gt;https:&#x2F;&#x2F;www.jstor.org&#x2F;stable&#x2F;24964580&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Polymorphic function mapping in C++</title>
        <published>2018-06-08T00:00:00+00:00</published>
        <updated>2018-06-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tommoa.me/blog/poly/"/>
        <id>https://tommoa.me/blog/poly/</id>
        
        <content type="html" xml:base="https://tommoa.me/blog/poly/">&lt;p&gt;In 2016, Jonathan Blow published a &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;Mo6_tJFeNMM?t=23m50s&quot;&gt;video demo for his upcoming (but still unreleased) programming language Jai&lt;&#x2F;a&gt;. In it, he does a demo about how the polymorphic solver in the Jai compiler is much better than the C++ version, using a demo of trying to pass a polymorphic function to another polymorphic function without explicitly stating the type as his proof, stating that it might be possible in C++17.&lt;&#x2F;p&gt;
&lt;p&gt;While he is certainly correct that the Jai polymorphic solver is (from the video at least) a lot more powerful than C++&#x27;s, as well as significantly better looking (no one likes looking at templates, lets be honest), he&#x27;s incorrect about not being able to implicitly pass a polymorphic function to another polymorphic function, so long as you use a C++11 compatible compiler.&lt;&#x2F;p&gt;
&lt;p&gt;The secret lies with the &lt;code&gt;decltype&lt;&#x2F;code&gt; specifier &lt;a href=&quot;http:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;cpp&#x2F;language&#x2F;decltype&quot;&gt;introduced in C++11&lt;&#x2F;a&gt;. &lt;code&gt;decltype&lt;&#x2F;code&gt; (and &lt;code&gt;auto&lt;&#x2F;code&gt;, also introduced in C++11) allows us to get the type of an object at compile type without having to specify what the type actually is. This is great for polymorphic functions as we suddenly no longer have to specify any types at all, save that which we pass in.&lt;&#x2F;p&gt;
&lt;p&gt;So using the same example as Jonathan used, a transformative map, we can actually avoid using any specific type specifiers in our program. I&#x27;m going to use &lt;code&gt;std::vector&amp;lt;&amp;gt;&lt;&#x2F;code&gt; instead of an array, but the principle is the same.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start by having a polymorphic function to print out our arrays, and our polymorphic incrementer. These will form the backbone which we use to solve our types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(std::vector&amp;lt;T&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::cout &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;&amp;quot;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; arr)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;        std::cout &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::cout &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;&amp;quot;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; std::endl;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;incr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(T &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;decltype&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will notice that while we declare the return type of our incrementer to be &lt;code&gt;auto&lt;&#x2F;code&gt;, we also declare a trailing return type with &lt;code&gt;decltype&lt;&#x2F;code&gt;. This is very similar to what Jonathan attempted, but he tried replacing the &lt;code&gt;auto&lt;&#x2F;code&gt; with just a &lt;code&gt;decltype&lt;&#x2F;code&gt;. In C++11, if you want a type deduced return value, you must state the type of the function to be &lt;code&gt;auto&lt;&#x2F;code&gt; and have a trailing &lt;code&gt;decltype&lt;&#x2F;code&gt; statement (This was relaxed in C++14 to no longer require the trailing &lt;code&gt;decltype&lt;&#x2F;code&gt;, though having the &lt;code&gt;decltype&lt;&#x2F;code&gt; still helps with template deduction on occasion).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; std::result_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(T&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;)&amp;gt;::type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(std::vector&amp;lt;T&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, F&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;decltype&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(std::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;vector&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;R&amp;gt;()) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;R&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;i) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;            out[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr[i]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; out;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can see our map function. Most likely the first thing that you&#x27;d notice is the &lt;code&gt;std::result_of&amp;lt;&amp;gt;&lt;&#x2F;code&gt; in the middle of our template declaration. &lt;a href=&quot;http:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;cpp&#x2F;types&#x2F;result_of&quot;&gt;&lt;code&gt;std::result_of&amp;lt;&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is another compile time type declaration resolver. It takes a function and its arguments and evaluates what its return type is. We use &lt;code&gt;F&amp;amp;&amp;amp;(T&amp;amp;&amp;amp;)&lt;&#x2F;code&gt; inside &lt;code&gt;std::result_of&amp;lt;&amp;gt;&lt;&#x2F;code&gt; because there are a few quirks with it that we would hit into using &lt;code&gt;F(T)&lt;&#x2F;code&gt;, such as discarding cv-qualifiers and automatically adjusting arrays and function types to pointers. If you&#x27;re using C++17 and above, &lt;code&gt;std::result_of&amp;lt;&amp;gt;&lt;&#x2F;code&gt; no longer exists due to those quirks, and so instead you can use &lt;code&gt;std::invoke_result&amp;lt;F, T&amp;gt;::type&lt;&#x2F;code&gt;, which looks one hell of a lot better.&lt;&#x2F;p&gt;
&lt;p&gt;Finally we come to our test function.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, incr));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And... it fails to compile. The reason why is that the compiler doesn&#x27;t know the way in which &lt;code&gt;incr&lt;&#x2F;code&gt; will be used inside of the &lt;code&gt;map&lt;&#x2F;code&gt; function, so it can&#x27;t infer the function type that we are actually passing. Once again, we can solve this by using a &lt;code&gt;decltype&lt;&#x2F;code&gt; to avoid having to use any nasty types:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, incr&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;decltype&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array)::value_type&amp;gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If that&#x27;s too ugly for you, you could declare a macro that does it instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;poly_map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(v, f&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;decltype&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(v)::value_type&amp;gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;poly_map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, incr));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this compiles and works!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; clang++ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-std&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;c++11 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;template_poly.cpp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .&#x2F;a.out
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 2 3 4 5 }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 3 4 5 6 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What&#x27;s more, this actually works with anything that could be considered a function.&lt;&#x2F;p&gt;
&lt;p&gt;It works with normal functions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;long_incr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, long_incr));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; clang++ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-std&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;c++11 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;template_poly.cpp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .&#x2F;a.out
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 2 3 4 5 }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 3 4 5 6 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It works with lambdas:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, [](&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; clang++ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-std&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;c++11 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;template_poly.cpp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .&#x2F;a.out
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 2 3 4 5 }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 3 4 5 6 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In C++14 you can even replace the &lt;code&gt;long&lt;&#x2F;code&gt; in the lambda declaration with &lt;code&gt;auto&lt;&#x2F;code&gt;, or wrap the polymorphic function so you don&#x27;t need the &lt;code&gt;poly_map&lt;&#x2F;code&gt; wrap!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, [](&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; clang++ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-std&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;c++14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;template_poly.cpp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .&#x2F;a.out
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 2 3 4 5 }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 3 4 5 6 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It even works with &lt;code&gt;std::bind&lt;&#x2F;code&gt;ed member functions!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;Incr {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;incr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;gt; array &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    Incr i;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;print_array&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(array, std::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;bind&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;Incr::incr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;i, std::placeholders::_1)));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; clang++ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;-std&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9acc76;&quot;&gt;c++11 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;template_poly.cpp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; .&#x2F;a.out
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 2 3 4 5 }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; 3 4 5 6 }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So that&#x27;s C++11. What does the C++14 or C++17 code look like?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5f697a;&quot;&gt;&#x2F;&#x2F; C++14
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; std::result_of&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(T&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;)&amp;gt;::type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(std::vector&amp;lt;T&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, F&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;R&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;i) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;            out[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr[i]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; out;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5f697a;&quot;&gt;&#x2F;&#x2F; C++17
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; std::invoke_result&amp;lt;F, T&amp;gt;::type&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(std::vector&amp;lt;T&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;arr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;, F&lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    std::vector&amp;lt;R&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; arr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;i) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;            out[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(arr[i]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; out;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;template &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;typename&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;incr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(T &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5f697a;&quot;&gt;&#x2F;&#x2F; and also
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; incr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;[](&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve lost our trailing return types and we can now use &lt;code&gt;auto&lt;&#x2F;code&gt; for lambda parameters!&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also a fun quirk on g++ that allows for &lt;code&gt;auto&lt;&#x2F;code&gt; to be used as a function parameter, even though you&#x27;re not supposed to until C++20.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; style=&quot;background-color:#2b303b;color:#6c7079;&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5cb3fa;&quot;&gt;incr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eb6772;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cd74e8;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#adb7c9;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db9d63;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#abb2bf;&quot;&gt;; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can find the full code of everything used here &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Tommoa&#x2F;Snippets&#x2F;blob&#x2F;master&#x2F;others&#x2F;template_poly.cpp&quot;&gt;on my github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Never underestimate the power of a good template!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
