<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gray Calhoun&apos;s academic homepage</title>
    <description>Updates from Gray Calhoun&apos;s homepage</description>	
    <link>http://gray.clhn.org</link>
    <atom:link href="http://gray.clhn.org/feed.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Expectations for “econometrics” PhD students</title>
      <description>&lt;p&gt;A list of expectations for students planning to do a field in Econometrics.&lt;/p&gt;
</description>
      <pubDate>Wed, 13 Apr 2016 00:00:00 +0000</pubDate>
      
      <link>https://slack-files.com/T0F8SPJGJ-F0WMAGK4Y-7cb66a33a8</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/econometrics-field</guid>
    </item>
    
    <item>
      <title>LaTeX CV template</title>
      <description>&lt;p&gt;I recently read Karen Kelsky’s (“Dr. Karen’s”) excellent &lt;a href=&quot;http://theprofessorisin.com/2012/01/12/dr-karens-rules-of-the-academic-cv/&quot;&gt;academic CV
rules&lt;/a&gt; and tried to follow her advice and revise &lt;a href=&quot;http://gray.clhn.org/dl/calhoun-cv.pdf&quot;&gt;my CV&lt;/a&gt;. It
seems like other people could find it useful too, so I wrote up
most of the changes as a LaTeX document class (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safecv&lt;/code&gt; document
class) and put it &lt;a href=&quot;https://github.com/grayclhn/safecv&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The repository gives you a document class that sets up formatting for
section headers, etc. and also gives you two empty-ish templates to
use for your own CV. One is tailored a bit towards grad students
entering the academic job market for the first time, and one is more
generic. I’m not a graphic designer, and you’re probably not either,
so the CV uses Times New Roman. It is the default, conservative,
“professional” font for those of us who predate Office 2007, which is
essentially everyone who will be in a position to hire you. (Since I
have no impulse control, I took this opportunity to &lt;a href=&quot;https://tug.org/store/lucida/&quot;&gt;buy the Lucida
TeX fonts&lt;/a&gt; and could not be happier with how they look. But my wife
still insists that my CV looks better in Times.)&lt;/p&gt;

&lt;p&gt;Is it a great CV template? Nope. Is it better than most of the other
CV templates I’ve seen? Yep. Almost entirely because, as Dr. Karen
suggests, all of the important dates are flush left and the text is
relentlessly left-aligned. Most of the other CV templates I’ve seen
are much slicker looking, but they put key information in different
random spots in different sections of the document. Don’t do that.&lt;/p&gt;

&lt;p&gt;Please open an issue on &lt;a href=&quot;https://github.com/grayclhn/safecv/issues&quot;&gt;GitHub&lt;/a&gt; if you find errors. Pull requests
are welcome too. And read &lt;a href=&quot;http://theprofessorisin.com/2012/01/12/dr-karens-rules-of-the-academic-cv/&quot;&gt;Dr. Karen’s advice&lt;/a&gt; most of all.&lt;/p&gt;

</description>
      <pubDate>Thu, 09 Jul 2015 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/cv-template</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/cv-template</guid>
    </item>
    
    <item>
      <title>Information about PhD Econometrics this Fall at Iowa State</title>
      <description>&lt;p&gt;(This is the text of an email I sent to incoming PhD students for Iowa
State. Maybe it’s useful for other people too.)&lt;/p&gt;

&lt;p&gt;Hi everyone,&lt;/p&gt;

&lt;p&gt;My name’s Gray Calhoun and I’m going to be teaching your Econometrics
class at Iowa State this fall (Econ 671). There is a preliminary
version of the syllabus on the course homepage,
&lt;a href=&quot;http://gray.clhn.org/671&quot;&gt;http://gray.clhn.org/671&lt;/a&gt;, but it may be changed slightly before the
semester starts. This email has a little more information about our
expectations and some advice on preparing for the class.&lt;/p&gt;

&lt;p&gt;First, this class is going to introduce you to statistical
programming, and we’re going to use the language R for all of the
assignments. If you have not programmed in R before, you may want to
start to familiarize yourself with it over the summer. Fortunately,
it’s free. You can download R from &lt;a href=&quot;http://cran.r-project.org&quot;&gt;http://cran.r-project.org&lt;/a&gt; (or
using your OS’s package manager). You should also install RStudio,
which can be downloaded for free from &lt;a href=&quot;http://www.rstudio.com&quot;&gt;http://www.rstudio.com&lt;/a&gt;, and
use it as the editor/IDE for R. (It is much better than using R
directly, and we’ll use RStudio in class.)&lt;/p&gt;

&lt;p&gt;Then, to actually become familiar with R, you may want to work through
a short tutorial. Two that are recommended are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Try R, &lt;a href=&quot;http://tryr.codeschool.com&quot;&gt;http://tryr.codeschool.com&lt;/a&gt; (it works in your web browser)&lt;/li&gt;
  &lt;li&gt;Swirl, &lt;a href=&quot;http://swirlstats.com&quot;&gt;http://swirlstats.com&lt;/a&gt; (through the R console).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also documentation for RStudio on its homepage.&lt;/p&gt;

&lt;p&gt;Second, if you haven’t taken a statistics or econometrics class
before, or if you last took one a few years ago, you’ll benefit from
reviewing some basic undergraduate textbooks.  I recommend the
following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Freedman, Pisani, and Purves’s “Statistics.” It’s currently on the
4th edition, but you can buy an older edition. (Or get a copy from
the library, you’re probably not going to need it as a reference.)
This is a very, very basic stats 101 level treatment. E.g. it
doesn’t really get more advanced than the t-test and you can
probably read it in a week. But it will give you a good
introduction to probability and statistics if you’ve never seen them
before.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tufte’s “Data Analysis for Politics and Policy.” This is a very
simple introduction to linear regression. It doesn’t get into the
math very much, but it is captures the intuition pretty well. It’s
available for $2 from Tufte’s website,
&lt;a href=&quot;http://www.edwardtufte.com/tufte/ebooks&quot;&gt;http://www.edwardtufte.com/tufte/ebooks&lt;/a&gt;. Again, this is the sort
of book you can read in about a week and it will give you a decent
introduction to the second half of our class.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reading through both of those books will give you an overview of what
we’re going to do in the class and shouldn’t take that long. So please
try to do it if you haven’t seen this material before. Do keep in mind
that these books are not representative of the mathematical level of
the course.&lt;/p&gt;

&lt;p&gt;If you’ve already seen this material, and have free time this summer
that you’d like to spend preparing for the econometrics sequence,
please feel free to email me and I will be happy to provide more
suggestions. Working through the recommended text, Freedman’s
“Statistical Models, Theory and Practice,” and doing the book’s
exercises in R would be very good preparation, but I can give other
recommendations too. :)&lt;/p&gt;

&lt;p&gt;In any case, I’m very happy you’ll be attending Iowa State and I look
forward to meeting you in August. Enjoy the summer!&lt;/p&gt;
</description>
      <pubDate>Wed, 20 May 2015 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/intro-phd-email</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/intro-phd-email</guid>
    </item>
    
    <item>
      <title>A visual analysis of some macroeconomic series</title>
      <description>&lt;p&gt;Slides for a presentation to the &lt;a href=&quot;http://dicook.github.io/graphics.html&quot;&gt;Statistical Graphics Working
Group&lt;/a&gt; in the Fall, 2014.&lt;/p&gt;
</description>
      <pubDate>Mon, 10 Nov 2014 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/dl/graphics_slides.pdf</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/macro-graphics</guid>
    </item>
    
    <item>
      <title>Short macros and utility functions for Julia</title>
      <description>&lt;p&gt;Link to a GitHub Gist with some short examples of Julia macros. Please
add to it!&lt;/p&gt;
</description>
      <pubDate>Mon, 20 Oct 2014 00:00:00 +0000</pubDate>
      
      <link>https://gist.github.com/grayclhn/5e70f5f61d91606ddd93</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/julia-macros2</guid>
    </item>
    
    <item>
      <title>Preliminary notes on Julia’s macros</title>
      <description>&lt;p&gt;First things first, I’m entirely unqualified to write a review, or
even an email or a tweet, discussing macros in Julia. I don’t know
anything. That said, I’m scheduled to give a 50 minute talk on
Wednesday about macros in Julia, so I need to do some research and
organize my thoughts. And you, dear reader, are reading the result of
that research and the mechanism for organizing my thoughts. So be
skeptical of everything you read here: it’s just my opinion, and my
opinion isn’t especially well-informed. A better resource is &lt;a href=&quot;http://julia.readthedocs.org/en/latest/manual/metaprogramming/&quot;&gt;Julia’s
documentation on metaprogramming&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-are-macros-how-are-they-different-than-functions&quot;&gt;What are macros? How are they different than functions?&lt;/h2&gt;

&lt;p&gt;Julia’s functions, like functions in most languages, take a collection
of arguments, run some instructions on them, and return a
value. Julia’s macros, on the other hand, take a collection of
expressions, run some transformations on them, and return Julia
code. That new code is run in place of the original macro.&lt;/p&gt;

&lt;p&gt;Now, what does that mean? I’ll go back to &lt;a href=&quot;http://julialang.org/blog/2013/09/fast-numeric&quot;&gt;my first love in Julia&lt;/a&gt;,
Dahua Lin’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@devec&lt;/code&gt; macro. Let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; be numeric vectors that
have the same length and suppose that we want to do some simple math
on their elements and store the results in a new vector &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;. Like
this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# basic version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You might disagree, but this is clearly the way we want to write these
operations: our intent is unambiguous. But this isn’t the way we want
the computer to execute these operations. As Dahua points out, it’s
slow and uses more memory than necessary, because each operation is
executed sequentially: first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-y&lt;/code&gt; is calculated and stored in a
temporary array (call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp1&lt;/code&gt;); then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abs(temp1)&lt;/code&gt; is executed and
stored in an array we can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp2&lt;/code&gt;; then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-temp2&lt;/code&gt; is executed and
stored in an array &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;temp3&lt;/code&gt;; and finally &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exp(temp3)&lt;/code&gt; is executed and
stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;. Each intermediate step traverses its input, which takes
time, and stores its output in a new array, which takes memory.&lt;/p&gt;

&lt;p&gt;Dahua argues that we’d like to run the code&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;                                &lt;span class=&quot;c&quot;&gt;# version 2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which is faster and more memory efficient. The operations still create
temporary variables, but those variables are now scalars and not
vectors, and we only traverse the array once. Potentially noticable
gains.&lt;/p&gt;

&lt;p&gt;I’d go even further. The first line of that code frightens me, because
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; can be a vector of integers but we’d still exect that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; would be
floats (and, indeed, when you run this code with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; as an integer, it
fails with an error). Second, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; can have different
lengths. The code as written implicitly checks that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x[i]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y[i]&lt;/code&gt;
are legitimate indexes, but it does it at each step of the loop. It
would be faster to check before the loop starts, and turn off checking
inside the loop. (There’s another macro, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@inbounds&lt;/code&gt;, that turns it
off.) So I’d prefer to use the code&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# version 3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@inbounds&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code does the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Checks that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; have the same length.&lt;/li&gt;
  &lt;li&gt;Calculates the first element of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exp(-abs(x - y))&lt;/code&gt; so that we can
learn its type.&lt;/li&gt;
  &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; only have one element, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstval&lt;/code&gt; and
stop. Otherwise, allocate an array for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;, store &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstval&lt;/code&gt; as its first
element, and then iterate our calculations down the rest of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, assuming that the indexes are valid for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Running all three options on my laptop with 80,000,000 elements gives
the timings listed in the table below (I wrapped the code in trivial
functions for the timings; &lt;a href=&quot;https://gist.github.com/grayclhn/2e43a628e67c007446e0&quot;&gt;this Gist has executable code&lt;/a&gt;.)&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Version&lt;/th&gt;
      &lt;th&gt;   &lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Elapsed time (sec)&lt;/th&gt;
      &lt;th&gt;   &lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Memory allocated (MB)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;7.21&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2,560&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5.03&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;640&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4.84&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;640&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We obviously want to run the last version of the code. (The second
version is essentially as efficient, but will throw an error if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; is
an integer.) But, just as obviously, the last version of the code is
hideous; so much so that I felt like it needed external documentation!
So we clearly want to &lt;em&gt;write&lt;/em&gt; the first version, but &lt;em&gt;execute&lt;/em&gt; the
second version.&lt;/p&gt;

&lt;h2 id=&quot;baby-steps-towards-writing-a-simple-devectorization-macro&quot;&gt;Baby steps towards writing a simple devectorization macro&lt;/h2&gt;

&lt;p&gt;This is my first macro. Fun!&lt;/p&gt;

&lt;p&gt;I’ll walk through the steps I took. First, as recommended in Paul
Graham’s &lt;a href=&quot;http://www.paulgraham.com/onlisp.html&quot;&gt;On Lisp&lt;/a&gt;, we’ll write out a representative call to the
macro and the expression that we actually want evaluated. And let’s
start with a baby version of the expression first:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@ourdevec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# representative call&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# baby expression goal&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So now we want to write code that converts the first expression to the
second. Julia expressions are represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr&lt;/code&gt; objects and they
have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args&lt;/code&gt; field. (This is being revisted and eventually
may change, though.) Here, we have&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;                                     &lt;span class=&quot;c&quot;&gt;# value returned&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;                  &lt;span class=&quot;c&quot;&gt;# value returned&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And looking at the type of each of the argumets gives&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;                  &lt;span class=&quot;c&quot;&gt;# value returned&lt;/span&gt;
 &lt;span class=&quot;kt&quot;&gt;Symbol&lt;/span&gt;
 &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So the left side is just a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Symbol&lt;/code&gt; (the variable type Julia uses for
variable names) and the right side is another Expr. We could keep on
going sub-expression by sub-expression, but fortunately there are
several functions that present everything at once for us:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show_sexpr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which tells us that each sub-expression is a function call, until we
finally get to the symbols &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:y&lt;/code&gt;. It also shows us that the
first element of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args&lt;/code&gt; for a function call is the symbol that
represents the function, and the rest of the elements are the
expressions or symbols passed to that function as arguments.&lt;/p&gt;

&lt;p&gt;To produce our baby expression, we want to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:y&lt;/code&gt; in
our original expression with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:(x[1])&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:(y[1])&lt;/code&gt;. More generally,
we want to take every symbol that’s not a function, and replace it
with a reference to its first element. (&lt;em&gt;Important realization&lt;/em&gt;: what
if we want to mix in scalars? Then this might not work! Oh crap! Let’s
disregard that problem for now and worry about it tomorrow. This post
is hard enough as it is.)&lt;/p&gt;

&lt;p&gt;This replacement is something we can do pretty easily with recursion,
since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:(x[1])&lt;/code&gt; is just another type of expression (a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:ref&lt;/code&gt;). We’ll
define two functions that help:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt;
              &lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;so&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getindex(:x, 1)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:(x[1])&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getindex(:(x - y), 1)&lt;/code&gt; calls both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getindex(:x, 1)&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getindex(:y, 1)&lt;/code&gt;; takes the result; and puts them together in the
original expression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getindex&lt;/code&gt; already exists and is the function that’s called when you
write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x[i]&lt;/code&gt; for arrays, so it seems reasonable to extend its methods
like this.&lt;/p&gt;

&lt;p&gt;The baby macro is dead simple now&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; our_devec_p1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# Ver 1 (baby macro)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and we can verify that it “does the right thing” by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;macroexpand&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macroexpand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@our_devec_p1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_38_firstval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))))&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# Value returned&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A note on what happened to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstval&lt;/code&gt;: since macros write out code
that’s executed in-place, there’s a chance that it could clobber
variables that already exist. Macros, unlike functions, don’t define
their own scope. To avoid overwriting existing variables, variables in
macros are given unique names. (The function that does this is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt;.) The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_38_&lt;/code&gt; represents the unique identifier added to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstval&lt;/code&gt; to make it unique. (The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; really displays as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; and
screws up our code highlighting; I’ve manually replaced the symbol.)&lt;/p&gt;

&lt;h2 id=&quot;two-more-tiny-steps-towards-a-devectorization-macro&quot;&gt;Two more tiny steps towards a devectorization macro&lt;/h2&gt;

&lt;p&gt;If we look back at the expanded code, we can see three distinct parts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Evaluate the vectorized expression for the first element. We’ve
already done this part.&lt;/li&gt;
  &lt;li&gt;Check that the vectors have the same length, and check that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;
has more than one element.&lt;/li&gt;
  &lt;li&gt;Loop over the elements of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; and assign the results of
each calculation to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This parallels our initial description, but now we’re going to
implement the second and third parts in the macro.&lt;/p&gt;

&lt;p&gt;First add the length check. Setting up the problem just like we did
for the baby macro earlier, we start with the expression&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and we need to produce&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can write similar functions as before (which is a sign that we
might want to think about generalizing this as utility code, but
nevermind that for now…)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which will recurse down a nested expression until it finds the symbols
at the bottom, then return a single array that lists them
all. (Putting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt; at the end of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr&lt;/code&gt; method flattens the
results.)&lt;/p&gt;

&lt;p&gt;It’s clumsy, but we can assemble the expression we need by hand, as
the next macro shows.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; our_devec_p2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comparison&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(I’m sure that there’s a slick, functional way to assemble the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_lengths&lt;/code&gt; expression, but I don’t know it.) Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;macroexpand&lt;/code&gt;
to verify that we’re on the right track gives&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macroexpand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@our_devec_p2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# value returned&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now the loop. Again, the expression we start with is&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and now the expression we want to return is&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;### Ignore the `else` part for now&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The body of the loop is &lt;em&gt;almost&lt;/em&gt; what we did before when we calculated
the first element, but now we don’t want &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; to create a new
variable name, we want to clobber &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;. Julia, forntunately, offers a
mechansim for “unhygenic” macros through the function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esc&lt;/code&gt;, which
works as follows&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; our_devec_part3&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You should expand this part on your own to verify that it works. (It
does, though.)&lt;/p&gt;

&lt;h2 id=&quot;finishing-the-macro&quot;&gt;Finishing the macro&lt;/h2&gt;

&lt;p&gt;We can put the three steps together for our final devectorization
macro:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;macro&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; our_devec&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;                        &lt;span class=&quot;c&quot;&gt;# Final version&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getvecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comparison&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;c&quot;&gt;# Part 2&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;@assert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_lengths&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# Part 1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# Part 3&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;@inbounds&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vecs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getindex&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;esc&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstval&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;# new but easy&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And one final expansion to verify that it does what we’d hoped:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macroexpand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@our_devec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# none, line 10:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;nothing&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;assertion failed: length(x) == length(y)&quot;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 11:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_51_firstval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])))&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 12:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 13:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similar&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_51_firstval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 14:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_51_firstval&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 15:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;boundscheck&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_52_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# line 16:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_52_i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_52_i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_52_i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])))&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;boundscheck&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# line 19:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_51_firstval&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(I was happily surprised that the index of the for loop is taken care
of automatically.)&lt;/p&gt;

&lt;p&gt;So now the code&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@our_devec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;runs as fast and with the same memory allocation as the explicitly
devectorized code from before. You can download all of the code for
this post &lt;a href=&quot;https://gist.github.com/grayclhn/2e43a628e67c007446e0&quot;&gt;here&lt;/a&gt;. (Obvious caveats are that the code is probably
pretty fragile and you’d probably need to make it more robust if you
use it for real.)&lt;/p&gt;

&lt;h2 id=&quot;are-macros-just-about-performance&quot;&gt;Are macros just about performance?&lt;/h2&gt;

&lt;p&gt;The devectorize macro we defined is representative of a class of
macros: it takes Julia code that would run fine otherwise, and it
rewrites the code to use the computer more efficiently. (The Julia
manual calls these “&lt;a href=&quot;http://julia.readthedocs.org/en/latest/manual/performance-tips/#performance-annotations&quot;&gt;Performance Annotations&lt;/a&gt;”). Some other macros
like this are&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@inbounds&lt;/code&gt;, which we’ve seen already&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@parallel&lt;/code&gt;, which can split loops across multiple processors to be
run in parallel&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@devec&lt;/code&gt; (the real version) which does more general devectorization.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@simd&lt;/code&gt;, which enables &lt;a href=&quot;https://software.intel.com/en-us/articles/vectorization-in-julia&quot;&gt;some sort of CPU-level devectorization that
I don’t understand&lt;/a&gt; but looks impressive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m sure there are a few others, but these are, as far as I can tell,
unrepresentative. Most macros are not written just to translate blocks
of Julia code into blocks of faster Julia code.  Dahua’s blog post was
the first thing I read that got me really excited about Julia, though,
so if I’m going to talk about macros….  But the main use of macros,
at least historically (and “historically” here means “in Lisp, as far
as I can tell.” Julia’s not old enough for any usage to be “historic”)
is extending the language by adding new features.&lt;/p&gt;

&lt;p&gt;First, a small example of language extensions. Perl, if you haven’t
used it, is a programming language that excels at text
manipulation. It does other things well too, and it was probably as
important to web programming during the dot-com bubble as JavaScript
has been for the whole Ajax/Web 2.0 [bubble]. One of the reasons why
Perl is great at text manipulations is because it has &lt;em&gt;excellent&lt;/em&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Regular_expression&quot;&gt;Regular Expressions&lt;/a&gt; (“regexes”), giving it an entire
mini-language for finding and replacing patterns in strings.&lt;/p&gt;

&lt;p&gt;Perl’s regexes are built into the language—large parts of the
language are built around them—so they’re fast and immediately
available. Julia has regexes as well, but they’re implemented as a
macro. (My understanding is that this is how Common Lisp implements
them as well.) Since these macro calls are translated before any code
is actually run, the regex is parsed once, in advance, and they’re
fast too.&lt;/p&gt;

&lt;p&gt;So both languages have fast regexes. But the implementation methods
are very different and the difference matters when you or I want to
add a feature like regexes to the language; say (hypothetically) a
regression modeling language like R’s, or a different text-processing
minilanguage. With Perl, new features will never have the same
performance or support that the built-in features do. With Julia, your
macros are on equal footing with the native ones, so these new
features have exactly the same support and potential for performance
as the “built in” regex.&lt;/p&gt;

&lt;p&gt;For flashier examples, there are at least two packages that support
pattern matching through the macro system. (&lt;a href=&quot;https://matchjl.readthedocs.org/en/latest/&quot;&gt;Match.jl&lt;/a&gt; and
&lt;a href=&quot;https://github.com/toivoh/PatternDispatch.jl&quot;&gt;PatternDispatch.jl&lt;/a&gt;; you’ll have to look at the packages to really
understand what they enable, but these are like powerful switch
statements.) And support for DocStrings is (finally) being added to
Base Julia, as a macro that was originally developed in a separate
package (&lt;a href=&quot;https://github.com/MichaelHatherly/Docile.jl&quot;&gt;Docile.jl&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;alternatives-to-macros&quot;&gt;Alternatives to macros&lt;/h2&gt;

&lt;p&gt;Another question: could we have written &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@our_devec&lt;/code&gt; as a function?
Can we write macros as functions in general? Julia functions can take
expressions as arguments and can return unevaluated expressions, and
Julia provides an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; function that evaluates expressions on the
fly. Specifically, would&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;our_devec&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;do the same thing as&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@our_devec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As implemented in Julia, the answer is clearly “no.” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; has weird
scoping issues: it evaluates expressions in the global scope, so if
it’s called inside a function it wouldn’t have access to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;. (I’ve read several places that this is for performance.)&lt;/p&gt;

&lt;p&gt;But, even if it’s not the way Julia implements it, we can certainly
imagine a “local eval” function. And we can certainly imagine people
who don’t care about performance. So, without those constraints, do
macros provide anything that we can’t get from evaluating expressions
returned from functions?&lt;/p&gt;

&lt;p&gt;I don’t think so, but I could be wrong. One reason is an &lt;em&gt;R-News&lt;/em&gt;
article by Thomas Lumley (2001), “&lt;a href=&quot;http://www.r-project.org/doc/Rnews/Rnews_2001-3.pdf#section*.31&quot;&gt;Overcoming R’s Virtues&lt;/a&gt;,” that
describes how to implement Lisp-style macros through R’s
functions. (Unlike Julia, R lets functions evaluate expressions in
essentially &lt;em&gt;whatever environment you want&lt;/em&gt;.) So, from a conceptual
standpoint, macros are just one mechanism for transforming expressions
and choosing where to evaluate them, and there are potentially many
other conceptually equivalent ways to do that.&lt;/p&gt;

&lt;p&gt;“Conceptual equivalence” and “practical equivalence” are very
different things, of course. The hypothetical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; version of macro
execution would have to parse the expression on the fly each time it’s
called, which we’d expect would give it a performance penalty compared
to a “native” implementation and is going to make them less appealing
in real applications. One of the driving principles in Julia’s
development has been the idea that user-added functionality should be
just as good as built-in functionality. This was part of the reason
that Julia’s numeric types are implemented in Julia, and not as
specialized C code, and it’s part of the reason that macros are used
to implement fundamental objects like regexes: putting them on equal
footing forces the language to support all of these extensions really
well.&lt;/p&gt;

&lt;p&gt;And obviously, performance-oriented macros like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@our_devec&lt;/code&gt; are off
the table without a real macro system.&lt;/p&gt;

&lt;h2 id=&quot;other-things-to-read&quot;&gt;Other things to read&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://julia.readthedocs.org/en/latest/manual/metaprogramming/&quot;&gt;Julia’s metaprogramming documentation&lt;/a&gt; (it’s unfortunately
sparse.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/JuliaOpt/JuMP.jl&quot;&gt;JuMP.jl&lt;/a&gt; and &lt;a href=&quot;https://github.com/JuliaStats/DataFramesMeta.jl&quot;&gt;DataFramesMeta.jl&lt;/a&gt; heavily use macros and are
probably going to be interesting to people who have read this far.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Given Lisp’s clear influence on Julia’s macro system, it’s probably
worth reading the &lt;a href=&quot;http://www.jstatsoft.org/v13&quot;&gt;special volume on Lisp-Stat of the &lt;em&gt;Journal of
Statistical Software&lt;/em&gt;&lt;/a&gt;, but it unfortunately does not say
anything about macros.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.paulgraham.com/onlisp.html&quot;&gt;Paul Graham’s &lt;em&gt;On Lisp&lt;/em&gt;&lt;/a&gt; is widely recommended and also
free. I’ve only read the first chapter on macros so far.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Here are links to the
&lt;a href=&quot;http://gray.clhn.org/dl/macros_etc.pdf&quot;&gt;slides&lt;/a&gt;,
&lt;a href=&quot;http://gray.clhn.org/dl/macros_etc.jl&quot;&gt;julia code&lt;/a&gt;, and
their &lt;a href=&quot;https://github.com/heike/stat590f/tree/master/macros&quot;&gt;source code&lt;/a&gt;
from the talk itself (given on 10/22)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I’ve started a short file with some basic macros and utility
functions on GitHub: &lt;a href=&quot;https://gist.github.com/grayclhn/5e70f5f61d91606ddd93&quot;&gt;https://gist.github.com/grayclhn/5e70f5f61d91606ddd93&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
      <pubDate>Mon, 13 Oct 2014 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/julia-macros</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/julia-macros</guid>
    </item>
    
    <item>
      <title>TBL talk on open-ended team activities</title>
      <description>&lt;p&gt;Some short notes I presented to the Iowa State “TBL” meeting; it went
over one of the team activities I’ve done with my econometrics
class. I got lots of good feedback and suggestions. I presented the
contents of this outline, but as slides.&lt;/p&gt;

&lt;h2 id=&quot;background-on-the-class-i-teach&quot;&gt;Background on the class I teach&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Started TBL this semester&lt;/li&gt;
  &lt;li&gt;Teach PhD Econometrics (basically a statistics class)
    &lt;ul&gt;
      &lt;li&gt;Core required class in the Econ department&lt;/li&gt;
      &lt;li&gt;Mostly Economics PhD students (one or two students from other
departments)&lt;/li&gt;
      &lt;li&gt;19 students this year (fairly typical class size)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;3 teams with 6 to 7 students&lt;/li&gt;
  &lt;li&gt;In first lecture, I sold TBL as a way for the students to get
experience with “open ended and poorly defined problems,” which
will help them in their research&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;example-of-one-team-activity&quot;&gt;Example of one team activity&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;../pictures/forecasting1.png&quot;&gt;
  &lt;img alt=&quot;TBL Activity Slide 1&quot; src=&quot;../pictures/forecasting1.png&quot; width=&quot;500&quot; border=&quot;1&quot; /&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;../pictures/forecasting2.png&quot;&gt;
  &lt;img alt=&quot;TBL Activity Slide 2&quot; src=&quot;../pictures/forecasting2.png&quot; width=&quot;500&quot; border=&quot;1&quot; /&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;../pictures/forecasting3.png&quot;&gt;
  &lt;img alt=&quot;TBL Activity Slide 3&quot; src=&quot;../pictures/forecasting3.png&quot; width=&quot;500&quot; border=&quot;1&quot; /&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;../pictures/forecasting4.png&quot;&gt;
  &lt;img alt=&quot;TBL Activity Slide 4&quot; src=&quot;../pictures/forecasting4.png&quot; width=&quot;500&quot; border=&quot;1&quot; /&gt;
  &lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;some-comments&quot;&gt;Some comments&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;There is no “right answer” but there are many, many “wrong
answers”&lt;/li&gt;
  &lt;li&gt;Potential for an answer being /wrong/ seems more important for
team’s internal discussion than whether or not it can be /right/&lt;/li&gt;
  &lt;li&gt;I’m having trouble getting much discussion between teams, though
    &lt;ul&gt;
      &lt;li&gt;If teams all choose wildly different approaches, they don’t have
a lot to say to each other&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;This might be addressed with better homework &amp;amp; preparation
    &lt;ul&gt;
      &lt;li&gt;For HW, students come up with different potential approaches&lt;/li&gt;
      &lt;li&gt;Decide on a list of allowed approaches early in the class period&lt;/li&gt;
      &lt;li&gt;Teams are required to choose and defend one of those options&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;last-comments&quot;&gt;Last comments&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Don’t expect students to magically figure out the “right way” to
handle challenging problems&lt;/li&gt;
  &lt;li&gt;“Problem solving” needs to be taught as well&lt;/li&gt;
  &lt;li&gt;Early on, you may want to split a problem into several small steps
and lead the students through it&lt;/li&gt;
  &lt;li&gt;Or, make “planning” something that the students are required to do
and are graded on before “acting”&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Fri, 03 Oct 2014 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/tbl-activity-talk</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/tbl-activity-talk</guid>
    </item>
    
    <item>
      <title>Cobbling together parallel random number generation in Julia</title>
      <description>&lt;p&gt;I’m starting to work on some computationally demanding projects,
(Monte Carlo simulations of bootstraps of out-of-sample forecast
comparisons) so I thought I should look at Julia some
more. Unfortunately, since Julia’s so young (it’s almost at version
0.3.0 as I write this) a lot of code still needs to be written. Like
Random Number Generators (RNGs) that work in parallel. So this post
describes an approach that parallelizes computation using a standard
RNG; for convenience I’ve put the code (a single function) is in a
grotesquely ambitiously named package on GitHub:
&lt;a href=&quot;https://github.com/grayclhn/ParallelRNGs.jl&quot;&gt;ParallelRNGs.jl&lt;/a&gt;. (Also see &lt;a href=&quot;http://thread.gmane.org/gmane.comp.lang.julia.user/17383&quot;&gt;this thread&lt;/a&gt; on the Julia Users mailing
list.)&lt;/p&gt;

&lt;p&gt;A few quick points about RNGs and simulations. Most econometrics
papers have a section that examines the performance of a few
estimators in a known environment (usually the estimators proposed by
the paper and a few of the best preexisting estimators). We do this by
simulating data on a computer, using that data to produce estimates,
and then comparing those estimate to the parameters they’re
estimating. Since we’ve generated the data ourselves, we actually know
the true values of those parameters, so we can make a real
comparison. Do that for 5000 simulated data sets and you can get a
reasonably accurate view of how the statistics might perform in real
life.&lt;/p&gt;

&lt;p&gt;For many reasons, it’s useful to be able to reproduce the exact same
simulations again in the future. (Two obvious reasons: it allows other
researchers to be able to reproduce your results, and it can make
debugging much faster when you discover errors.) So we almost always
use pseudo Random Number Generators that use a deterministic algorithm
to produce a stream of numbers that behaves in important ways like a
stream of independent random values. You initialize these RNGs by
setting a starting value (the “pseudo” aspect of the RNGs is implicit
from now on) and anyone who has that starting value can reproduce the
identical sequence of numbers that you generated. A popular RNG is the
“&lt;a href=&quot;http://en.wikipedia.org/wiki/Mersenne_twister&quot;&gt;Mersenne Twister&lt;/a&gt;,” and “popular” is probably an understatement:
it’s the default RNG in R, Matlab, and Julia. And (from what I’ve
read; this isn’t my field at all) it’s well regarded for producing a
sequence of random numbers for statistical simulations.&lt;/p&gt;

&lt;p&gt;But it’s not necessarily appropriate for producing several independent
sequences of random numbers. Which is vitally important because I have
an 8 core workstation that needs to run lots of simulations, and I’d
like to execute 1/8th of the total simulations on each of its cores.&lt;/p&gt;

&lt;p&gt;There’s a common misconception that you can get independent random
sequences just by choosing different initial values for each sequence,
but that’s not guaranteed to be true. There are algorithms for
choosing different starting values that are guaranteed to produce
independent streams for the Mersenne Twister (&lt;a href=&quot;http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html&quot;&gt;see this research by
one of the MT’s inventors&lt;/a&gt;), but they aren’t implemented in Julia
yet. (Or in R, as far as I can tell; they use a different RNG for
parallel applications.) And it turns out that Mersenne Twister is the
only RNG that’s included in Julia so far.&lt;/p&gt;

&lt;p&gt;So, this would be a perfect opportunity for me to step up and
implement some of these advanced algorithms for the Mersenne
Twister. Or to implement some of the algorithms developed by &lt;a href=&quot;http://www.iro.umontreal.ca/~lecuyer/&quot;&gt;L’Ecuyer
and his coauthors&lt;/a&gt;, which are what R uses. And there’s already C
code for both options.&lt;/p&gt;

&lt;p&gt;But I haven’t done that yet. :(&lt;/p&gt;

&lt;p&gt;Instead, I’ve written an extremely small function that wraps Julia’s
default RNG, calls it from the main process alone to generate random
numbers, and then sends those random numbers to each of the other
processes/cores where the rest of the simulation code runs. The
function’s really simple.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; replicate&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dgp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; rvproducer&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;produce&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dgp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pmap&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sim&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvproducer&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That’s all. If you’re not used to Julia, you can ignore the
“::Function” and the “::Integer” parts of the arguments. Those just
identify the datatype of the argument and you can read it as
“dgp_function” if you want (and explicitly providing the types like
this is optional anyway). So, you give “replicate” two functions:
“dgp” generates the random numbers and “sim” does the remaining
calculations; “n” is the number of simulations to do. All of the work
is done in “&lt;a href=&quot;http://julia.readthedocs.org/en/latest/manual/parallel-computing/#scheduling&quot;&gt;pmap&lt;/a&gt;” which parcels out the random numbers and sends
them to different processors. (There’s a simplified version of the
source code for “pmap” at that link.)&lt;/p&gt;

&lt;p&gt;And that’s it. Each time a processor finishes one iteration, pmap
calls “dgp()” again to generate more random numbers and passes them
along. It automatically waits for “dgp()” to finish, so there are no
race conditions and it produces the exact same sequence of random
numbers every time. The code is shockingly concise. (It shocked me! I
wrote it up assuming it would fail so I could understand pmap better
and I was pretty surprised when it worked.)&lt;/p&gt;

&lt;p&gt;A quick example might help clear up it’s usage. We’ll write a DGP for
the bootstrap:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# Number of observations for each simulation&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nboot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;299&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Number of bootstrap replications&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;addprocs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;# Start the other 7 cores&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dgp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nboot&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The data are iid Normal, (the “randn(n)” component) and it’s an iid
nonparametric bootstrap (the “rand(1:n, (n, nboot))”, which draws
independent values from 1 to n and fills them into an n by nboot
matrix).&lt;/p&gt;

&lt;p&gt;We’ll use a proxy for some complicated processing step:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@everywhere&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; sim&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;nboot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bootvals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Float64&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nboot&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nboot&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bootvals&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;confint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quantile&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bootvals&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.05&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# not usually recommended!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;confint&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confint&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So “sim” calculates the mean of each bootstrap sample and calculates
the 5th and 95th percentile of those simulated means, giving a
two-sided 90% confidence interval for the true mean. Then it checks
whether the interval contains the true mean (0). And it also wastes 3
seconds sleeping, which is a proxy for more complicated calculations
but usually shouldn’t be in your code. The initial “@everywhere” is a
Julia macro that loads this function into each of the separate
processes so that it’s available for parallelization. (This is
probably as good a place as any to link to Julia’s “Parallel
Computing” documentation.)&lt;/p&gt;

&lt;p&gt;Running a short Monte Carlo is simple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;84537423&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Initialize the default RNG!!!&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mc1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replicate&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sim&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dgp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;elapsed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;217.705639&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;508892580&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allocated&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.13&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mf&quot;&gt;0.896&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# = 448/500&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, about 3.6 minutes and the confidence intervals have coverage
almost exactly 90%.&lt;/p&gt;

&lt;p&gt;It’s also useful to compare the execution time to a purely sequential
approach. We can do that by using a simple for loop:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; dosequential&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;boots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Float64&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;boots&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sim&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dgp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boots&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And, to time it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dosequential&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Force compilation before timing&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;84537423&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Reinitialize the default RNG!!!&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;julia&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@time&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mc2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dosequential&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;elapsed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1502.038961&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;877739616&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allocated&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.03&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mf&quot;&gt;0.896&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# = 448/500&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This takes a lot longer: over 25 minutes, 7 times longer than the
parallel approach (exactly what we’d hope for, since the parallel
approach runs the simulations on 7 cores). And it gives exactly the
same results since we started the RNG at the same initial value.&lt;/p&gt;

&lt;p&gt;So this approach to parallelization is great… sometimes.&lt;/p&gt;

&lt;p&gt;This approach should work pretty well when there aren’t that many
random numbers being passed to each processor, and when there aren’t
that many simulations being run; i.e. when “sim” is an inherently
complex calculation. Otherwise, the overhead of passing the random
numbers to each process can start to matter a lot. In extreme cases,
“dosequential” can be faster than “replicate” because the overhead of
managing the simulations and passing around random variables dominates
the other calculations. In those applications, a real parallel RNG
becomes a lot more important.&lt;/p&gt;

&lt;p&gt;If you want to play with this code yourself, I made a small package
for the replicate function: &lt;a href=&quot;https://github.com/grayclhn/ParallelRNGs.jl&quot;&gt;ParallelRNGs.jl&lt;/a&gt; on GitHub. The name
is misleadingly ambitious (ambitiously misleading?), but if I do add
real parallel RNGs to Julia, I’ll put them there too. The code is
still buggy, so use it at your own risk and let me know if you run
into problems. (Filing an issue on GitHub is the best way to report
bugs.)&lt;/p&gt;

&lt;p&gt;P.S. I should mention again that Julia is an absolute joy of a
language. Package development isn’t quite as nice as in Clojure, where
it’s straightforward to load and unload variables from the package
namespace (again, there’s lots of code that still needs to be
written). But the actual language is just spectacular and I’d probably
want to use it for simulations even if it were slow. Seriously: seven
lines of new code to get an acceptable parallel RNG.&lt;/p&gt;

</description>
      <pubDate>Tue, 08 Jul 2014 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/parallel-rng-in-julia</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/parallel-rng-in-julia</guid>
    </item>
    
    <item>
      <title>Slowly moving to Julia from R</title>
      <description>&lt;p&gt;&lt;a href=&quot;http://julialang.org/&quot;&gt;Julia&lt;/a&gt; is a new computing language that’s gotten a lot of
attention lately (e.g., &lt;a href=&quot;http://www.wired.com/wiredenterprise/2014/02/julia/&quot;&gt;this Wired piece&lt;/a&gt;) and that I’ve ignored
until recently. But I checked it out a few days ago and, holy crap,
it’s a nice language. I’m rewriting the code in my book to use Julia
instead of R and I’m almost certainly going to use it instead of R in
my PhD class next fall.&lt;/p&gt;

&lt;p&gt;So, why Julia and why not R? (And, I suppose why not
Python/Matlab/other languages?)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple dispatch&lt;/strong&gt; — so you can define a function&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;TrickyAlgorithm&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aThing&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bThing&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;differently to depend on whether “aThing” is a matrix of real numbers
and “bThing” is is a vector, or “aThing” is a vector and “bThing” is a
matrix, or any other combinations of data types. And you can do this
without lots of tedious, potentially slow, and confusing (to people
reading and maintaining the code) argument checks and conversion
within the function.&lt;/p&gt;

&lt;p&gt;This is a form of Object Oriented Programming, but in typical OOP
“TrickyAlgorithm” would need to be a method of “aThing” or
“bThing”. Also note that multiple dispatch is present in R as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Homoiconicity&lt;/strong&gt; — the code can be operated on by other parts of the
code. Again, R kind of has this too! Kind of, because I’m unaware of a
good explanation for how to use it productively, and R’s syntax and
scoping rules make it tricky to pull off. But I’m still excited to see
it in Julia, because &lt;a href=&quot;http://www.paulgraham.com/avg.html&quot;&gt;I’ve heard good things about macros&lt;/a&gt; and I’d
like to appreciate them (I’ve started playing around with Clojure and
like it a lot too…). And because stuff like this is amazing:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@devec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which devectorizes x and y (both vectors) and evaluates as&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(This example and code is from &lt;a href=&quot;http://julialang.org/blog/2013/09/fast-numeric/&quot;&gt;Dahua Lin’s blog post, “Fast Numeric
Computation in Julia.”&lt;/a&gt;) Note that “evaluates as” does not mean
“gives the same answer as,” it means that the code “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r =
exp(-abs(x-y))&lt;/code&gt;” is replaced with the loop by “@devec” and then the
loop is what’s run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed&lt;/strong&gt; — definitely faster than well written R; I don’t have a
great feel for how well it compares to highly optimized R (using
inline C++, for example), but I write one-off simulation programs and
don’t write highly optimized R.And the language encourages loops,
which is a relief. R discourages loops and encourages “vectorized”
operations that operate on entire objects at once (which are then
converted to fast loops in C…). But I use loops all the time anyway,
because avoiding loops in time series applications is impossible. R’s
poor support for recursion doesn’t help either.And, more to the point,
I teach econometrics to graduate students. Many of them haven’t
programmed before. Most of them are not going to write parts of their
analysis in C++.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The syntax&lt;/strong&gt; is fine and unthreatening, which will help for
teaching. It basically looks like Matlab done right. Matlab’s not a
bad language because its programs look like they’re built out of
Legos, it’s a bad language because of its horrendous implementation of
functions, anonymous functions, objects, etc. Compared to R, Matlab
and Julia look downright friendly. Compared to Clojure… I can’t even
imagine asking first year PhD students (some with no programming
experience at all) to work with a Lisp.&lt;/p&gt;

&lt;p&gt;The last point that’s always mentioned in these language
comparisons. What about all of the R packages? There are thousands and
thousands of statistical packages coded up for R, and you’re giving
that up by moving to a different language.This is apparently a big
concern for a lot of people, but… have you looked at the source code
for these packages? Most of them are terrible! But some are good, and
it might take some time to port them to Julia. Not that much time, I
think, because most high-performance popular R packages are a thin
layer of interoperability over a fast implementation in C or C++, so
the port is just a matter of wrapping it up for Julia. And most of the
well designed packages are tools for other package developers.That’s
not quite true of R’s statistical graphics, though. They’re really
great and could be hard to port. And that’s more or less the only
thing that I’m sure that I’ll miss in Julia. (But hopefully not for
too long.)&lt;/p&gt;

&lt;p&gt;Lastly, and this is important: the same massive quantity of packages
for R is a big constraint on its future development. Breaking
backwards compatibility is a big deal but avoiding it too much imposes
costs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Anyway&lt;/strong&gt;, since I converted some R code to Julia I thought it would be
fun to compare speeds. The first example is used to show the sampling
distribution of an average of uniform(0,1) random variables. In R, we
have&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;n&quot;&gt;rstats&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which is (I think) pretty idiomatic R (and is vectorized, so it’s
supposed to be fast). Calling it gives&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system.time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rstats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#     user  system elapsed&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#    0.341   0.002   0.377&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For comparison to the Julia results, we’re going to care about the
“elapsed” result of 0.377 seconds; the “system” column isn’t relevant
here.  Calling it for more observations and more simulations (50,000
of each) gives&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system.time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rstats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runif&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;50000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;50000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#      user  system elapsed&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#   204.184   0.217 215.526&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;so 216 seconds overall. And, just to preempt criticism, I ran these
simulations a few times each and these results are representative; and
I ran a byte-compiled version that got (unexpectedly) slightly worse
performance.&lt;/p&gt;

&lt;p&gt;Equivalent Julia code is&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; rmeans&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;means&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Float64&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;means&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;means&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which is pretty easy to read, but I have no idea if it’s
idiomatic. This is my first code in Julia. If you like to minimize
lines of code and preallocation of arrays, Julia has list
comprehensions and you can write the stylish one line definition (that
gave similar times)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-julia&quot; data-lang=&quot;julia&quot;&gt;&lt;span class=&quot;n&quot;&gt;rmeans_pretty&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;x&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nobs&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsims&lt;/span&gt; &lt;span class=&quot;x&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can time  (after loading the Distributions packages):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-jlcon&quot; data-lang=&quot;jlcon&quot;&gt;julia&amp;gt; @elapsed rmeans(Uniform(), 500)
### 0.093662961&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;so 0.09 seconds, or about a quarter the time as R. But (I forgot to
mention earlier), Julia uses a Just In Time compiler, so the 0.09
seconds includes compilation and execution. Running it a second time
gives&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-jlcon&quot; data-lang=&quot;jlcon&quot;&gt;julia&amp;gt;  @elapsed rmeans(Uniform(), 500)
### 0.004334132&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which (as a reader had to point out to me) is 1/20th the time
again. So we are getting into the ~100 times faster range.&lt;/p&gt;

&lt;p&gt;Running the larger simulation, we have&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-jlcon&quot; data-lang=&quot;jlcon&quot;&gt;julia&amp;gt; @elapsed rmeans_loop(Uniform(), 50000, nsims = 50000)
### 77.318591953&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;so the R code is a little less than three times slower here. (The
compilation step doesn’t make a meaningful difference.) So, Julia
isn’t hundreds of times faster, but it is noticeably faster than R,
which is nice.&lt;/p&gt;

&lt;p&gt;But speed in this sort of test isn’t the main factor. I’m really
excited about multiple dispatch — it’s one of the few things in R that
I really, really liked from a language standpoint. I really like what
I’ve read about Julia’s support for parallelism (but need to learn
more). And I like metaprogramming, even if I can’t do it myself
yet. So Julia’s trying to be a fast, easy to learn, and elegantly
designed language. That’s awesome. I want it to work.&lt;/p&gt;

&lt;p&gt;ps: and it’s open source! Can’t forget that.&lt;/p&gt;

</description>
      <pubDate>Tue, 18 Feb 2014 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/julia-intro</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/julia-intro</guid>
    </item>
    
    <item>
      <title>Quick thoughts and advice on whether to get a PhD in economics</title>
      <description>&lt;p&gt;A friend emailed me to ask about grad school; I thought I might as
well share my thoughts here too. First, I should make it clear that I
basically never recommend getting a PhD to anyone. Grad school pays
almost nothing, is very stressful, damages most people’s
relationships, exacerbates any latent depression or anxiety issues you
might have, and the only payoff is that you’ll get to learn about one
or two things in intense, intense detail for years. So I emphasize the
negatives, reasoning that if you can hear all the downsides and still
think, “screw it, sounds like fun”… then going to grad school
&lt;em&gt;might&lt;/em&gt; be a good idea. But if I can scare you away, then you never
should have tried to get a PhD in the first place.&lt;/p&gt;

&lt;p&gt;That said, here are some more thoughts, in no particular order.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;If you’re going to get a PhD in the social sciences, or anything
close to the social sciences, it should be in economics. You can do
pretty much any of the other disciplines, but you’ll get paid
considerably more and there are more academic positions, private
sector and government jobs, etc available. Doing economics in a
business school may be even better.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I’d only suggest getting a PhD if you want a job teaching and/or
doing research as a professor or at a research institute or
think-tank. I don’t think that there are that many other jobs where
the training is going to help. I’m sure there are jobs where having
a PhD would be a nice addition for a candidate, but probably not so
much that it’s worth 5–6 years of full time school. Of course, you
might know of particular positions that I don’t.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you actually, you know, have a job, career, life, etc., that
you’d be putting on hold for grad school (which is the case for the
friend I mentioned above, but wasn’t for me when I applied) you
should probably be pretty selective about where you’d go; so top 10
or so only. Basically, you want a setup where, even if grad school
goes badly and the job market is terrible when you graduate, you can
have a job “better” than what you have now on graduation. That’s
probably true if you go to Harvard, MIT, Stanford, etc., but not
necessarily if you go to, say, UCSD. Obviously, you want to know who
you plan to work with, but people change their minds once they get
to grad school all the time, so being at a great school will give
you options if you change your mind.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you’re coming straight out of college, or if you have a bad job
with poor career prospects (I was working as a file clerk in the
post dot-com bubble Bay Area two years after I graduated from
college), you can take a bigger risk and go to a top 30 school that
matches your presumed research interests. UCSD turned out to be a
great fit for me, mostly because I was right when I expected to do
econometrics.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The first year of grad school (in Econ) will be really tough and
unpleasant if you’ve been out of school for a little while. There’s
a lot of math and it may have been a little while since you sat down
and worked through proofs, etc. Expect that the core sequence of
classes will be tough.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;other-opinions&quot;&gt;Other opinions&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://noahpinionblog.blogspot.de/2013/05/if-you-get-phd-get-economics-phd.html&quot;&gt;Noah Smith is much more positive than I am&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://chrisblattman.com/about/contact/gradschool/&quot;&gt;Chris Blattman is more specific&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://faculty-gsb.stanford.edu/athey/gradadvising.html&quot;&gt;Susan Athey’s advice on applying to grad schools&lt;/a&gt;
looks great and you should definitely read it.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Sat, 01 Jun 2013 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/econ-grad-school</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/econ-grad-school</guid>
    </item>
    
    <item>
      <title>Numeric stability in Clojure&apos;s statistics package, Incanter</title>
      <description>&lt;p&gt;&lt;strong&gt;See below for some updates; and I don’t follow Clojure’s
development, so the whole post might be out of date by the time you’re
reading it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve been casually interested in Lispy languages for a while; i.e. I’d
like to learn one and am not going to let the fact that I only know
bits of elisp after 15 years of using Emacs deter me.  Clojure seems
hot and I really like the talks I’ve seen by Rich Hickey, its creator.
&lt;a href=&quot;http://www.infoq.com/presentations/Simple-Made-Easy#.UWTGZZuG4ks.wordpress&quot;&gt;Simple Made Easy&lt;/a&gt;
is especially good.  Plus, Clojure even has a well-regarded statistics
library, &lt;a href=&quot;http://incanter.org/&quot;&gt;Incanter&lt;/a&gt;, so awesome.&lt;/p&gt;

&lt;p&gt;Anyway, procrastinating tonight, I decided to check out
&lt;a href=&quot;https://github.com/liebke/incanter&quot;&gt;Incanter’s source code on Github&lt;/a&gt;.
I have a really simple method for evaluating open source statistics
packages: find the linear regression function, and look for variables
named xpxi or xtxi and, if they exist, basically avoid the package
(for some reason, these variable names are ubiquitous.).  Inverting
the &lt;em&gt;X’X&lt;/em&gt; matrix is a pretty bad idea–it is a numerically unstable way
of calculating the regression coefficients that (in problems I’ve
worked on) sometimes leads to a non-idempotent projection matrix
&lt;em&gt;X(X’X)⁻¹X’&lt;/em&gt; (or, using less terminology, &lt;em&gt;X’X(X’X)⁻¹&lt;/em&gt; may not equal
the identity matrix).  Needless to say this results in pretty bad
estimates of the OLS coefficients.
&lt;a href=&quot;http://www.r-project.org/doc/Rnews/Rnews_2004-1.pdf#section*.31&quot;&gt;Douglas Bates talks about performance issues in this R-news
article&lt;/a&gt;
too, but I’m much more concerned about numeric instability.  I don’t
necessarily have the most informed opinion about the best way to get
the OLS estimates, but I’ve gotten good results from the QR
decomposition.&lt;/p&gt;

&lt;p&gt;As of today, you can probably guess,
&lt;a href=&quot;https://github.com/liebke/incanter/blob/master/modules/incanter-core/src/incanter/stats.clj#L2067&quot;&gt;Incanter fails this test&lt;/a&gt;.
The source code and documentation are pretty unconcerned with the
actual implementation of OLS, and I can’t figure out exactly what
algorithm solve uses (I’m unpersuaded by the claim that it is
“&lt;a href=&quot;https://github.com/liebke/incanter/blob/master/modules/incanter-core/src/incanter/core.clj#L682&quot;&gt;equivalent to R’s solve function&lt;/a&gt;”
and can’t really track it down any further than that part of the
code).&lt;/p&gt;

&lt;p&gt;These details are important!  I mean, I appreciate the effort and the
good intentions that goes into developing open source packages like
this.  But if you’re developing statistical software for other people
to use, you really need to understand the numeric properties of the
routines you’re writing and you need to transparently communicate that
understanding to other people who might use your code.  So I guess
I’ll stick with R for a while longer.&lt;/p&gt;

&lt;h2 id=&quot;update-on-july-7-2013&quot;&gt;Update on July 7, 2013&lt;/h2&gt;

&lt;p&gt;This post drew a response from an
Incanter user (who wants to stay anonymous, or I’d just quote the
email).  In short, the email pointed out that, if you know how Clojure
handles dependencies and libraries, it’s not hard to verify that
Incanter’s solve uses &lt;a href=&quot;http://www.netlib.org/lapack/explore-html/d7/d3b/group__double_g_esolve.html#ga5ee879032a8365897c3ba91e3dc8d512&quot;&gt;LAPACK’s DGESV&lt;/a&gt; from JBLAS to invert the
&lt;em&gt;X’X&lt;/em&gt; matrix using an LU factorization, which is the exact same
algorithm as &lt;a href=&quot;http://stat.ethz.ch/R-manual/R-devel/library/base/html/solve.html&quot;&gt;R’s solve&lt;/a&gt;, so my suspicion there was misplaced.
Great!&lt;/p&gt;

&lt;p&gt;Obviously my first reaction to the email was astonishment that
anyone’s read my blog.  But I think my original point still stands.
Looking for a variable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xtxi&lt;/code&gt; used to estimate OLS is a quick
and dirty way to evaluate a statistics package, because inverting the
&lt;em&gt;X’X&lt;/em&gt; matrix is numerically unsound compared to other methods of
estimating OLS. R, for example, does not use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve&lt;/code&gt; for OLS, &lt;a href=&quot;http://stat.ethz.ch/R-manual/R-patched/library/stats/html/lm.html&quot;&gt;it uses
the QR decomposition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s some R code where the difference matters (I don’t know Clojure,
but this uses the same algorithms).  This isn’t quite linear
regression, it’s a comparison of different methods for constructing
projection matrices, &lt;em&gt;P = X (X’X)⁻¹ X’&lt;/em&gt; (so it’s basically identical
to linear regression).  Here are three different methods:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;n&quot;&gt;projection.LU1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%*%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crossprod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%*%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crossprod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crossprod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.QR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tcrossprod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qr.Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pivot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seq_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rank&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The first inverts &lt;em&gt;X’X&lt;/em&gt; using the same algorithm in Incanter; the
second uses a slightly better version but is basically the same, and
the third uses the QR decomposition, just like R.&lt;/p&gt;

&lt;p&gt;From the mathematical definition, we can see that &lt;em&gt;P= PP&lt;/em&gt;, a property
called idempotence, which is an easy property to verify numerically.
Here’s a set of 51 observations for 11 regressors (each column is &lt;em&gt;z&lt;/em&gt;
raised to the &lt;em&gt;p&lt;/em&gt;th power for &lt;em&gt;p&lt;/em&gt; = 0, 1, 2,…,10 and &lt;em&gt;z&lt;/em&gt; between
zero and one).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;outer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now we can “verify” idempotence (up to numerical tolerance)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all.equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%*%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Mean relative difference: 0.0002737938&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all.equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%*%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.LU2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Mean relative difference: 0.0001990939&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all.equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.QR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.QR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%*%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projection.QR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;TRUE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All of the code is available for download here:
&lt;a href=&quot;https://gist.github.com/grayclhn/5717763&quot;&gt;https://gist.github.com/grayclhn/5717763&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see (and verify it for yourself by downloading the code) that
the first two methods of calculating &lt;em&gt;P&lt;/em&gt;, which invert &lt;em&gt;X’X&lt;/em&gt; using the
LU factorization &lt;strong&gt;just like Incanter&lt;/strong&gt;, are not idempotent.  The third
method, which uses the QR decomposition &lt;strong&gt;just like R&lt;/strong&gt;, is idempotent.
So in this example, the QR decomposition works and the LU
factorization doesn’t.&lt;/p&gt;

&lt;p&gt;This example is obviously contrived, but it’s not isolated.  Chapter
11 of &lt;a href=&quot;http://www.worldcat.org/title/linear-regression-analysis/oclc/300231427&quot;&gt;Seber and Lee’s (2003) &lt;em&gt;Linear Regression Analysis&lt;/em&gt;&lt;/a&gt; shows
the same thing: that if the regressors are “badly” distributed, the QR
decomposition is more reliable. (In the interest of full disclosure, I
should admit, embarrassing as it is, that chapter 11 of Seber and Lee
is essentially all I know about these issues, so I’m not claiming a
lot of expertise.)&lt;/p&gt;

&lt;p&gt;As one last point, let me preempt anyone who might respond, “yes,
these issues matter in those particular examples, but that will never
come up in real research.”  Try to guess why I look to see how a stats
package calculates the linear regression coefficients, and why I have
this particular criterion that I care about instead of any other, and
why….&lt;/p&gt;

&lt;p&gt;It’s obvious, right?  This is something I’ve personally screwed up
before.  An early version of my job-market paper had fantastic
empirical results that turned out to be entirely an artifact of using
&lt;em&gt;(X’X)⁻¹&lt;/em&gt; to calculate the F-test statistic instead of using the QR
decomposition and the “projection.QR” function in the code example is
copied directly from that project (a later version).  I was lucky and
paranoid enough to catch it before circulating the paper but the event
definitely left an emotional impression.&lt;/p&gt;
</description>
      <pubDate>Wed, 10 Apr 2013 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/clojure</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/clojure</guid>
    </item>
    
    <item>
      <title>An extremely subjective outline of the economics job market</title>
      <description>&lt;p&gt;I had promised that I’d consolidate the collected “job market wisdom”
of the 2009 graduating class and present it as a set of notes for
future classes.  I put it off (after getting a job, one still needs to
defend…) and I’ve forgotten a lot of the suggestions that other
people had.  So these notes largely reflect my own job market
experience.  I’ll try to include other people’s opinions when I can
remember them.  If you have comments or information that I missed,
please let me know.  Some people have and requested that they stay
anonymous, but I’m happy to attribute the advice to you if you want
credit.&lt;/p&gt;

&lt;p&gt;Since these documents last longer than is originally intended, I
should give a little bit of background information.  I went to
graduate school at UCSD where I studied econometrics for six years.  I
went on the job market in the 2008-2009 academic year and defended in
July, 2009.  My first job out of grad school is an Assistant
Professorship in the Economics Department at Iowa State University.&lt;/p&gt;

&lt;p&gt;— Gray Calhoun&lt;/p&gt;

&lt;h2 id=&quot;other-job-market-guides&quot;&gt;Other job market guides&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;John Crawley’s &lt;em&gt;Job Market Guide and Advice&lt;/em&gt; is the official guide,
and you should read it before reading any further here. (First,
because it’s better than my guide. Second, because I’m going to
assume you’ve read it.) The &lt;a href=&quot;https://www.aeaweb.org/joe/&quot;&gt;JOE website&lt;/a&gt; links to the latest
version.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://mitpress.mit.edu/books/guide-young-economist-0&quot;&gt;William Thomson’s &lt;em&gt;A Guide for the Young
Economist&lt;/em&gt;&lt;/a&gt;
covers the job market (in the second edition), and you should read
the book anyway.  Lucky you, the &lt;a href=&quot;http://mitpress.mit.edu/sites/default/files/titles/content/9780262016162_sch_0001.pdf&quot;&gt;sample
chapter&lt;/a&gt;
that MIT Press has put online is the one covering the job market.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;brief-time-frame-for-job-market&quot;&gt;Brief time frame for job market&lt;/h1&gt;

&lt;p&gt;A basic timeline: what happens when; what you need to own or create by
that date; and what you probably want in addition to the bare minimum.&lt;/p&gt;

&lt;h2 id=&quot;mid-october-through-end-of-november&quot;&gt;mid-October through end of November&lt;/h2&gt;

&lt;p&gt;The deadlines for job applications largely fall in late October
through mid November.  About a quarter of the applications are due
after Thanksgiving. At the miniumum, you need:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A generic cover letter: Writing more than one cover letter per
“class” of job application is overkill; I had one cover letter for
research positions (regardless of the department), one for private
sector jobs, and one for teaching positions.  They got tweaked a
little for some of the positions, but not by more than a sentence or
two (one example: I mentioned that “I worked closely with Dimitris
Politis” when applying to statistics departments).  The cover letter
needs to include this information:&lt;/p&gt;

    &lt;p&gt;Your field (and secondary fields if they’re relevant)&lt;/p&gt;

    &lt;p&gt;The position you’re applying for (sometimes the letter goes to HR.
Sometimes the department is hiring for several positions and the
same person handles all of it.  Etc.)&lt;/p&gt;

    &lt;p&gt;Your advisors names&lt;/p&gt;

    &lt;p&gt;The fact that you’ll attend the AEA meetings (It is not always
assumed that you’re attending the AEA meetings.  I was asked about
this by email a few times when I omitted it in the cover letter).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A paper (your “job market paper”): This should go without
saying.  I was surprised by how many people read my job market
paper, though.  Before going through the process, I had the
impression that job market papers were not actually read, but that
the interview decision was made largely on letters of
recommendation.  I was wrong.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Three letters of recommendation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A one to two page summary of your dissertation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A CV: UCSD encouraged us to use its template, which is
(unfortunately) very ugly.  It probably doesn’t matter if it is
ugly… but I didn’t use their template. &lt;a href=&quot;http://theprofessorisin.com/2012/01/12/dr-karens-rules-of-the-academic-cv/&quot;&gt;Karen Kelsky has fantastic
instructions for putting together a
CV&lt;/a&gt;,
and I tried to follow them the last time I rewrote my CV. A LaTeX
template is available &lt;a href=&quot;https://github.com/grayclhn/safecv&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A webpage. Nothing fancy, just links to your CV and your job market
paper, which should be clearly labeled “job market paper” if you
have more than one paper online (or even if you don’t). A picture of
yourself looking relaxed but professional is good too.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;additional-material-you-might-want-beyond-the-minimum&quot;&gt;Additional material you might want beyond the minimum&lt;/h3&gt;

&lt;p&gt;You may also need to put together a few things that many, but not all,
schools require. You don’t need to put much effort into these elements
of your application, unless you badly want a teaching job.  But many
schools will consider your application incomplete if it doesn’t have
these items included.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A summary of teaching evaluations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A one-page “statement of teaching philosophy.”&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, if you can pull it off, you’ll want these things too. (They are
highly recommended):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Another paper: “Highly recommended” is an understatement.  I
have heard rumors that the department (UCSD) will re-evaluate where
they’ll push a candidate on completion of a second paper.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Another letter of recommendation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A resume: If a job asks for “a resume,” it does not mean “a CV.”
A resume should have different information than a CV; for example,
computer skills and non-research work experience.  Obviously, if you
are only applying to academic jobs, you don’t need a resume and,
knowing that, you may not want to put your resume on your website
(having the resume on your website signals that you’re applying to
non-research jobs, which signals that you’re not confident about
your ability to land a research job, which signals lower
ability… I’m overthinking this, but not really kidding)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;miscellaneous-other-points-about-this-stage-of-the-job-market&quot;&gt;Miscellaneous other points about this stage of the job market:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;If you are not a native English speaker, you absolutely need to have
a classmate who is a native English speaker proofread all of your
jobmarket documents.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Other academic departments (other than economics; statistics or
public policy, for example) may be on a slightly earlier or later
schedule than the econ job market.  Government departments that
don’t hire many Ph.D. economists also can operate on a different
application schedule (the State Department, as a hypothetical
example), so (if they hire later) they can be useful for hedging.
You should be aware that these departments typically pay noticeably
less than institutions that hire lots of economists.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There’s disagreement on whether you should or should not apply for
jobs that are “out of reach.” I did. The cost of applying to any
given job is tiny, and it seemed like getting my paper read by as
many people as possible had benefits on its own.  I didn’t see a
downside, and don’t know what the counterargument is; but it does
apparently exist.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It is often easier to apply for a job than to determine whether or
not you are a good fit for that job.  If you find yourself agonizing
and trying to decide whether you should apply, save yourself some
time and apply.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Economics Department jobs are posted on JOE (the AEA’s website),
ERN, FRN, Walras.org, inomics, UK-JOE.  Most business schools,
government agencies, and private companies looking for
Ph.D. Economists post to JOE as well.  European departments
sometimes post here, sometimes post elsewhere.  Many smaller, less
prestigious liberal arts colleges won’t post anywhere but will have
faculty jobs listed on their HR website.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Other types of jobs can be posted elsewhere. For Public Policy:
&lt;a href=&quot;http://www.appam.org/home.asp&quot;&gt;APPM&lt;/a&gt;; Health Economics:
&lt;a href=&quot;http://www.academyhealth.org&quot;&gt;AcadamyHealth&lt;/a&gt;; Statistics:
&lt;a href=&quot;http://jobs.imstat.org&quot;&gt;IMS&lt;/a&gt;,
&lt;a href=&quot;http://www.amstat.org/jobweb/index.cfm&quot;&gt;ASA&lt;/a&gt;, and the &lt;a href=&quot;http://www.stat.ufl.edu/vlib/jobs.html&quot;&gt;online stats
job site&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Be aware that this process is stressful and busy for everyone. You
won’t be an exception.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;About organization: I kept an Excel file where each row contained
all of the information for a given job: deadline, department,
contact info, JEL codes, etc.  In retrospect, this was complete
overkill.  I made slight errors in transcribing the information, and
I went back and checked the original listing before writing each
cover letter.  The point is, you’re only sending 200 job packets at
most, so automating and computerizing the process is silly.  If I
were doing it over, I’d print out each job listing and keep it in a
binder sorted by the application deadline.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;in-the-first-two-to-three-weeks-after-thanksgiving&quot;&gt;In the first two to three weeks after Thanksgiving&lt;/h2&gt;

&lt;p&gt;Schools will contact you about interviews at the meetings.
This is more stressful than earlier, but not particularly busy.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Your advisor and committee can make phone calls.  Ask them to if
you’re not getting interviews. This stage is the one that your
advisor’s pull matters.  They can get you interviews at the AEA
meetings, not flyouts and certainly not jobs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are sales (Macy’s, after Thanksgiving, etc.) that are
especially helpful for buying luggage and suits.  Shopping would be
a nice way to blow off steam.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Generally, people perform worse in their first few interviews,
perform best in the early afternoon on the first day, and perform
worse again as they get fatigued later in the day and on the second
and third days.  If you could schedule your interviews to reflect
that pattern, it would be great.  But you really can’t.  You will
get calls about interviews over about a two week period; suppose the
first interview you get is very prestigious, and the next interview
is much less.  You have no way of knowing where they fall in the
distribution of interviews you’re going to have.  By the time you’ve
scheduled enough interviews to know how you should schedule them,
it’s too late.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;One thing you can do is know how far it is between hotels; this is
hard to do if you haven’t lived in the city, so ask someone who has.
Last year (January of 2009), some people didn’t realize that SF has
hills, and walking up those hills is more difficult than walking
down.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;first-few-days-of-january&quot;&gt;First few days of January&lt;/h2&gt;

&lt;p&gt;You’ll be at the AEA meetings, have fun! The biggest thing you’ll need
is to have practiced describing your job market paper and
dissertation! Professional attire and comfortable shoes are also a
good idea, but are much less important.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;You really are running from hotel room to hotel room for three (or
more) days; one of the only things I was surprised about was how
much my feet hurt.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You need to practice a lot for the interviews.  Practice with
friends.  There are lists online of potential questions specific to
the Economics job market.  The basic format is:&lt;/p&gt;

    &lt;p&gt;You sit down, someone says, “tell us about your research”
with some amusement.&lt;/p&gt;

    &lt;p&gt;You describe your job market paper – they may interrupt with
questions and they may not; it really depends on the interviewer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You want this period to be very busy.  It may or may not be stressful&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you are invited to a reception, you should go.  Even though
you’ll be tired and feel exhausted.  I skipped some and was asked
(by one of them) why I didn’t attend, so apparently people do
notice.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It is hard to describe how different various people’s experience was
at SF last year.  Some people had a great time and enjoyed meeting
with everyone.  Other people had interviews that they thought were
hostile and unpleasant.  In general, the people who resolved
beforehand that the experience would be fun usually had fun –
obviously, there’s a huge amount of endogeneity in that statement,
but it does mean that your experience is heavily influenced by your
attitude even if (and I don’t believe this) your outcomes are not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you have co-authored papers (I didn’t, but this advice comes from
someone who did), expect to be asked where the idea came from, who
did what, etc.  I assume this is even more likely if it is your job
market paper.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Some research has been done on what happens in a “bad” job market.
In short, the best candidates get more interviews and other
candidates get fewer and worse interviews.  Whether or not you
believe the results, this research suggests that whenever you’re
asked how the job market is going (by someone other than a close
confidant) you should reply, “I’m really happy with the interviews I
have and I’m busier than I expected to be.”  It’s plausibly true,
it’s a subtle signal that you’re a “good” candidate, and (most
importantly) it’s a much more pleasant answer than, “this year sucks
and I hate all of my interviews,” especially when you are asked the
question during an interview.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;january-and-february&quot;&gt;January and February&lt;/h2&gt;

&lt;p&gt;This is when flyouts and job negotiation. Here’s what you’ll need for
sure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A reliable laptop: If you have any doubt about the reliability
of your laptop, buy a new one.  The tiny netbooks only cost a few
hundred dollars.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Slides (well, pdfs if we’re being literal): Specifically,
you’ll need to give a polished job market presentation that runs
1:15 to 1:30. Different departments have different length seminars.
You should be practicing a lot.  You should also be aware that the
conference rooms vary a lot.  [UCSD students] are used to a short
and wide seminar room, others can be very long and skinny.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-basic-schedule-of-a-flyout&quot;&gt;The basic schedule of a flyout:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;You usually arrive the day/night before&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You’ll have dinner the night you interview or the night
 before. Sometimes, the “official” dinner will be the night after
 you interview, but people will want to take you out to an
 “unofficial” dinner the night before; so arrive early the day
 before if you can to keep that night’s dinner free.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Leave town that night or the next morning&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Interviews with the faculty run about half an hour to an hour.  you
may talk be about your paper, maybe about the university, maybe
about misc. topics (the Detroit lions losing, for example, or about
the university’s retirement plan).  The most fun interviews are when
you talk about the other person’s research.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The dinner may or may not be an “interview,” depending on who is
free that night. If it is an interview, one standard format is to
ask technical questions over dessert.  This can be done pleasantly
or not; at ISU, I was politely asked to explain how I planned to do
a few technical extensions to my job market paper that I’d discussed
earlier. So, you should not drink at dinner.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;An anonymous reader had the following comment: ‘It might be obvious,
but the job interview is the entire time you are with potential
colleagues on the fly-out – this includes dinners and happy hours
and drinks and whatever.  Some freshwater schools, in particular,
will wait to ask hard questions at the end of a dinner including
drinks, and perhaps even a happy hour before that.  Be professional
the whole time and be ready to be on your game (your research, the
particulars of what your job market does) whenever you are around
these potential colleagues.  Remember two parts to the term
“potential colleagues:” the “potential” means you have to know your
stuff around them, and they are very interested to know if you know;
the “colleague” means it pays to show that you are a human being
that can be sociable, and so isn’t a drag to have around.’&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;other-concerns-during-this-period&quot;&gt;Other concerns during this period&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Contacting institutions about nearby interviews is okay.  This
caused me some stress about what “nearby” means when you’re flying
out of San Diego, especially because people here have misconceptions
about actual distance between cities on the east coast.  I still
don’t know.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;After you get an offer, you can and should contact everyone else
that you interviewed with — they understand how the process works
and understand that you’re on a deadline.  If you hadn’t heard from
them since the AEA meetings, it’s almost certain that they’ll tell
you, “thanks for letting us know.  We’re going to hire someone
else.”  But it’s still important; it’s good for “networking;” and
they’ll probably say something like, “I really liked your research,”
which will make you feel good about yourself.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fly direct whenever possible.  There’s a temptation to try to save
the department paying for your flyout a little bit of money, but you
are going to be very tired and probably sick, and missing a
connecting flight could be a disaster.  No one ever was offered a
job for saving the department $300 on a plane ticket.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully this period is busy.  It is extremely stressful.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;general-points-about-the-process&quot;&gt;General points about the process&lt;/h1&gt;

&lt;p&gt;Here are a few things we did when I was on the job market that you
might find helpful. I haven’t seen them mentioned on other job market
guides.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;We set up a different mailing list.  People had to opt in to it, the
idea being that people are sometimes shy about sharing information
because they don’t want to come across as gloating or hurt someone’s
feelings if the job market is going particularly badly.  If people
opt in to a second mailing list, you can be at least somewhat
comfortable that they value the information.  Almost everyone
participated.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For the same reason, we set up a shared spreadsheet with everyone’s
interview information.  A spreadsheet format makes a little more
sense for organizing this information, and getting regular email
updates of everyone else’s great interviews is extremely irritating.
So we set up the spreadsheet separately.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We held practice interviews.  The Federal Reserve interviews on
campus before any of the scheduled faculty interviews, and we wanted
to practice for those interviews too.  Also, there are only two
interviews with faculty, and we wanted to practice a little bit more
than that.  I think that some of us did about 5-10 practice
interviews overall.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We attended each other’s practice job talk seminars, and scheduled
extras.  Again, the job talk matters, so having lots of practice is
helpful.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;speculative-points-on-networking&quot;&gt;Speculative points on networking&lt;/h2&gt;

&lt;p&gt;I didn’t do many of these things, but in retrospect wish that I had.
So take it for what it’s worth.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The job market is an excellent time to start “networking.”  After
the job market, you’re going to have a job (I am sure of this.  It
is a tautology).  One aspect of any job is “building a professional
network.”  If you were smart, you started this in grad school by
meeting speakers, going to conferences, following up with people,
paying attention to who’s working on what, etc.  But, like most of
us, you probably did an incomplete job of it.  This year, you are
going to meet a lot of people at a lot of different institutions,
and many of them are going to have very similar research interests
to yours — there’s a lot of self-selection.  So, approach the job
market from two angles: you do want a job, but you also want to
start meeting future collaborators.  This means: follow up with
people, write thank you notes after interviewing, try to talk to
them about their research and discuss common interests, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You will be very tempted to skip departmental seminars during the
Fall quarter and consequently avoid meeting the speakers.  Don’t.
There are many obvious reasons that you should continue to go to the
seminars and meet the speakers; I assume you can see them yourself.
Another, not at all obvious reason is that you are likely to take a
job at a department that does not have regular seminars in your
field – many departments have a single, weekly, “department
seminar” that hosts all outside speakers.  So this could be your
last year (for the foreseeable future) of working at a department
that has regular seminars in your field.  Take advantage of it while
it lasts.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A note about thank-you notes.  They’re not necessary, but they’re
nice.  Despite what you read in job-search books, write emails and
not hand-written letters.  People can and do reply to emails.
Moreover, since no one checks his or her department mailbox
regularly, you can’t be sure that a hand-written letter would even
be received.  Sending or not sending a note will make no difference
on whether or not you are hired, but getting hired shouldn’t be your
only goal this year.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Different advisors handle the job market differently.  Some advisors
are very upbeat before the market, some are very negative, some are
very hands-on, some aren’t.  Often candidates in consecutive years
who share the same advisor will have interviews at many of the same
places. So it probably makes sense to contact your advisor’s
previous advisees and ask them about their job market experience and
what you should expect.&lt;/p&gt;

    &lt;p&gt;First, it’s useful information on its own.&lt;/p&gt;

    &lt;p&gt;Also, you are doing similar research to your advisor’s previous
advisees, so you should know them. Even if you were friends in grad
school, it may have been a few years since you last talked.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For exactly the same reason, you may want to contact recent UCSD
grads who work in your field (Micro Theory, for example). (Speaking
from the future as someone who now gets contacted by UCSD grads,
it’s great. I enjoy it and it never feels like an imposition or
burden. More of you should do it.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For private sector jobs, and probably some government jobs, the
stereotypical private sector job search advice applies: talk to
people inside the companies you’re considering working at, and if
you don’t know someone working there, ask someone who does to
introduce you.  One of the job market guides (I think Stanford’s)
says (in a different context) that a job at an economic consulting
company is a sure thing for any of their graduates, which would
suggest that trying to get those jobs is a waste of time.  This may
or may not be true for UCSD graduates in a typical year, but
probably isn’t true in an exceptionally bad year.  Moreover, it
ignores an important point.  There are huge differences in working
at one company vs. another, in one branch vs. another, and in one
city vs. another.  Some of these differences are apparent to outside
applicants, but most aren’t; and some are clear but there’s no
reliable way for an outside applicant to control how the application
is handled.  The point of talking to people is to ensure that the
right branch/department in the right city in the right company is
handling your application and to make sure that you know what the
“right” one is for all of those variables.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Do not isolate yourself from other grad students.  This year is
extremely stressful, and almost no one else you know can empathize
with what you’re going through (it’s like being a teenager). Talk to
each other.  Go out to dinner at the AEA meetings.  Text each other.
One nice feature of the shared spreadsheet was that it removed
uncertainty about how other people are doing – which is nice on its
own, but also helped make it easier to talk about the job
market… instead of asking Chris (for example) “how’s it going?”
and worrying that he’ll respond by crying, I could say,
“congratulations on that new interview” or “man, why the hell aren’t
more places lining up to interview you?”&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Do not isolate yourself from your family.  Where you move affects
your family too.  Your spouse is also extremely stressed out.  This
can go a bit too far, though: I met a few candidate’s spouses at the
AEA meetings and found it a bit weird.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You may have noticed that this outline did not mention any of the
economics job-market rumor boards, wikis, etc.  They don’t have much
information, people on them lie, and it’s depressing and stressful
to read the messages.  I avoided them.  They may have improved since
I was on the job market, but I doubt it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Sat, 01 Aug 2009 00:00:00 +0000</pubDate>
      
      <link>http://gray.clhn.org/blog/job-market-notes</link>
      
      <guid isPermaLink="true">http://gray.clhn.org/blog/job-market-notes</guid>
    </item>
    
  </channel>
</rss>
