<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Martin Modrák</title>
    <description>The latest articles on Forem by Martin Modrák (@martinmodrak).</description>
    <link>https://forem.com/martinmodrak</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2517%2F9483603.jpeg</url>
      <title>Forem: Martin Modrák</title>
      <link>https://forem.com/martinmodrak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/martinmodrak"/>
    <language>en</language>
    <item>
      <title>Optional Parameters/Data in Stan</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Tue, 24 Apr 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/martinmodrak/optional-parametersdata-in-stan-4o33</link>
      <guid>https://forem.com/martinmodrak/optional-parametersdata-in-stan-4o33</guid>
      <description>

&lt;p&gt;Sometimes you are developing a &lt;a href="http://mc-stan.org"&gt;Stan&lt;/a&gt; statistical model that has multiple variants: maybe you want to consider several different link functions somewhere deep in your model, or you want to switch between estimating a quantity and getting it as data or something completely different. In these cases, you might have wanted to use optional parameters and/or data that apply only to some variants of your model. Sadly, Stan does not support this feature directly, but you can implement it yourself with just a bit of additional code. In this post I will show how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Base Model
&lt;/h2&gt;

&lt;p&gt;Let’s start with a very simple model: just estimating the mean and standard deviation of a normal distribution:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight mosel"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rstan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;knitr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tidyverse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cores&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parallel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;detectCores&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;rstan_options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_write&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3145678&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;model_fixed_code&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s2"&gt;"
data {
  int N;
  vector[N] X;
}

parameters {
  real mu;
  real&amp;lt;lower=0&amp;gt; sigma; 
}

model {
  X ~ normal(mu, sigma);

  //And some priors
  mu ~ normal(0, 10);
  sigma ~ student_t(3, 0, 1);
}

"&lt;/span&gt;

&lt;span class="n"&gt;model_fixed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;stan_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_fixed_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And let’s simulate some data and see that it fits:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mu_true = 8
sigma_true = 2
N = 10
X &amp;lt;- rnorm(N, mean = mu_true, sd = sigma_true)

data_fixed &amp;lt;- list(N = N, X = X)
fit_fixed &amp;lt;- sampling(model_fixed, data = data_fixed, iter = 500)
summary(fit_fixed, probs = c(0.1, 0.9))$summary %&amp;gt;% kable()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;mean&lt;/th&gt;
&lt;th&gt;se_mean&lt;/th&gt;
&lt;th&gt;sd&lt;/th&gt;
&lt;th&gt;10%&lt;/th&gt;
&lt;th&gt;90%&lt;/th&gt;
&lt;th&gt;n_eff&lt;/th&gt;
&lt;th&gt;Rhat&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mu&lt;/td&gt;
&lt;td&gt;7.855031&lt;/td&gt;
&lt;td&gt;0.0256139&lt;/td&gt;
&lt;td&gt;0.5632183&lt;/td&gt;
&lt;td&gt;7.162485&lt;/td&gt;
&lt;td&gt;8.548415&lt;/td&gt;
&lt;td&gt;483.5059&lt;/td&gt;
&lt;td&gt;1.007501&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sigma&lt;/td&gt;
&lt;td&gt;1.774158&lt;/td&gt;
&lt;td&gt;0.0206974&lt;/td&gt;
&lt;td&gt;0.4400573&lt;/td&gt;
&lt;td&gt;1.302616&lt;/td&gt;
&lt;td&gt;2.350727&lt;/td&gt;
&lt;td&gt;452.0508&lt;/td&gt;
&lt;td&gt;1.003409&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lp__&lt;/td&gt;
&lt;td&gt;-12.103350&lt;/td&gt;
&lt;td&gt;0.0555738&lt;/td&gt;
&lt;td&gt;1.1132479&lt;/td&gt;
&lt;td&gt;-13.664610&lt;/td&gt;
&lt;td&gt;-11.091775&lt;/td&gt;
&lt;td&gt;401.2768&lt;/td&gt;
&lt;td&gt;1.004955&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Now With Optional Parameters
&lt;/h2&gt;

&lt;p&gt;Let’s say we now want to handle the case where the standard deviation is known. Obviously we could write a new model. But what if the full model has several hundred lines and the only thing we want to change is to let the user specify the known standard deviation? The simplest solution is to just have all parameters/data that are needed in any of the variants lying around and use &lt;code&gt;if&lt;/code&gt; conditions in the model block to ignore some of them, but that is a bit unsatisfactory (and also those unused parameters may in some cases hinder sampling).&lt;/p&gt;

&lt;p&gt;For a better solution, we can take advantage of the fact that Stan allows zero-sized arrays/vectors and features the &lt;em&gt;ternary operator&lt;/em&gt; &lt;code&gt;?&lt;/code&gt;. The ternary operator has the syntax &lt;code&gt;(condition) ? (true value) : (false value)&lt;/code&gt; and works like an &lt;code&gt;if - else&lt;/code&gt; statement, but within an expression. The last piece of the puzzle is that Stan allows size of data and parameter arrays to depend on arbitrary expressions computed from data. The model that can handle both known and unknown standard deviation follows:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight mosel"&gt;&lt;code&gt;&lt;span class="n"&gt;model_optional_code&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s2"&gt;"
data {
  int N;
  vector[N] X;

  //Just a verbose way to specify boolean variable
  int&amp;lt;lower = 0, upper = 1&amp;gt; sigma_known; 

  //sigma_data is size 0 if sigma_known is FALSE
  real&amp;lt;lower=0&amp;gt; sigma_data[sigma_known ? 1 : 0]; 
}

parameters {
  real mu;

  //sigma is size 0 if sigma_known is TRUE
  real&amp;lt;lower=0&amp;gt; sigma_param[sigma_known ? 0 : 1]; 
}

transformed parameters {
  real&amp;lt;lower=0&amp;gt; sigma;
  if (sigma_known) {
    sigma = sigma_data[1];
  } else {
    sigma = sigma_param[1];
  }
}

model {
  X ~ normal(mu, sigma);

  //And some priors
  mu ~ normal(0, 10);
  if (!sigma_known) {
    sigma_param ~ student_t(3, 0, 1);
  }
}

"&lt;/span&gt;

&lt;span class="n"&gt;model_optional&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;stan_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_optional_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We had to add some biolerplate code, but now we don’t have to maintain two separate models. This trick is also sometimes useful if you want to test multiple variants in development. As the model compiles only once and then you can test the two variants while modifying other parts of your code and reduce time waiting for compilation.&lt;/p&gt;

&lt;p&gt;Just to make sure the model works and see how to correctly specify the data, let’s fit it assuming the standard deviation is to be estimated:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data_optional &amp;lt;- list(
  N = N,
  X = X,
  sigma_known = 0,
  sigma_data = numeric(0) #This produces an array of size 0
)

fit_optional &amp;lt;- sampling(model_optional, 
                         data = data_optional, 
                         iter = 500, pars = c("mu","sigma"))
summary(fit_optional, probs = c(0.1, 0.9))$summary %&amp;gt;% kable()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;mean&lt;/th&gt;
&lt;th&gt;se_mean&lt;/th&gt;
&lt;th&gt;sd&lt;/th&gt;
&lt;th&gt;10%&lt;/th&gt;
&lt;th&gt;90%&lt;/th&gt;
&lt;th&gt;n_eff&lt;/th&gt;
&lt;th&gt;Rhat&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mu&lt;/td&gt;
&lt;td&gt;7.854036&lt;/td&gt;
&lt;td&gt;0.0198265&lt;/td&gt;
&lt;td&gt;0.5440900&lt;/td&gt;
&lt;td&gt;7.181837&lt;/td&gt;
&lt;td&gt;8.531780&lt;/td&gt;
&lt;td&gt;753.0924&lt;/td&gt;
&lt;td&gt;0.9981102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sigma&lt;/td&gt;
&lt;td&gt;1.730077&lt;/td&gt;
&lt;td&gt;0.0152808&lt;/td&gt;
&lt;td&gt;0.3918781&lt;/td&gt;
&lt;td&gt;1.308565&lt;/td&gt;
&lt;td&gt;2.270505&lt;/td&gt;
&lt;td&gt;657.6701&lt;/td&gt;
&lt;td&gt;0.9989029&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lp__&lt;/td&gt;
&lt;td&gt;-11.992770&lt;/td&gt;
&lt;td&gt;0.0503044&lt;/td&gt;
&lt;td&gt;0.9811551&lt;/td&gt;
&lt;td&gt;-13.383729&lt;/td&gt;
&lt;td&gt;-11.089657&lt;/td&gt;
&lt;td&gt;380.4199&lt;/td&gt;
&lt;td&gt;1.0016842&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And now let’s run the model and give it the correct standard deviation:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data_optional_sigma_known &amp;lt;- list(
  N = N,
  X = X,
  sigma_known = 1,
  sigma_data = array(sigma_true, 1) 
  #The array conversion is necessary, otherwise Stan complains about dimensions
)

fit_optional_sigma_known &amp;lt;- sampling(model_optional, 
                                     data = data_optional_sigma_known, 
                                     iter = 500, pars = c("mu","sigma"))
summary(fit_optional_sigma_known, probs = c(0.1, 0.9))$summary %&amp;gt;% kable()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;mean&lt;/th&gt;
&lt;th&gt;se_mean&lt;/th&gt;
&lt;th&gt;sd&lt;/th&gt;
&lt;th&gt;10%&lt;/th&gt;
&lt;th&gt;90%&lt;/th&gt;
&lt;th&gt;n_eff&lt;/th&gt;
&lt;th&gt;Rhat&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mu&lt;/td&gt;
&lt;td&gt;7.808058&lt;/td&gt;
&lt;td&gt;0.0292710&lt;/td&gt;
&lt;td&gt;0.6273565&lt;/td&gt;
&lt;td&gt;7.017766&lt;/td&gt;
&lt;td&gt;8.622762&lt;/td&gt;
&lt;td&gt;459.3600&lt;/td&gt;
&lt;td&gt;1.006164&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sigma&lt;/td&gt;
&lt;td&gt;2.000000&lt;/td&gt;
&lt;td&gt;0.0000000&lt;/td&gt;
&lt;td&gt;0.0000000&lt;/td&gt;
&lt;td&gt;2.000000&lt;/td&gt;
&lt;td&gt;2.000000&lt;/td&gt;
&lt;td&gt;1000.0000&lt;/td&gt;
&lt;td&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lp__&lt;/td&gt;
&lt;td&gt;-11.072234&lt;/td&gt;
&lt;td&gt;0.0321233&lt;/td&gt;
&lt;td&gt;0.6750295&lt;/td&gt;
&lt;td&gt;-11.917321&lt;/td&gt;
&lt;td&gt;-10.585280&lt;/td&gt;
&lt;td&gt;441.5753&lt;/td&gt;
&lt;td&gt;1.002187&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Extending
&lt;/h2&gt;

&lt;p&gt;Obviously this method lets you do all sorts of more complicated things, in particular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the optional parameter is a vector you can have something like&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;vector[sigma_known ? 0 : n_sigma] sigma;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can have more than two variants to choose from and then use something akin to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;real param[varaint == 5 ? 0 : 1];&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your conditions become more complex you can always put them into a user-defined function (for optional data) or &lt;code&gt;transformed data&lt;/code&gt; block (for optional parameters) as in:&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;functions {
  int compute_whatever_size(int X, int Y, int Z) {
        //do stuff
  }
}

data {
  ...
  real whatever[compute_whatever_size(X,Y,Z)];
  real&amp;lt;lower = 0&amp;gt; whatever_sigma[compute_whatever_size(X,Y,Z)];
}

transformed data {
  int carebear_size;

  //do stuff
  carebear_size = magic_result;
}

parameters {
  vector[carebear_size] carebear;
  matrix[carebear_size,carebear_size] spatial_carebear;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




</description>
      <category>r</category>
      <category>stan</category>
      <category>bayesianstatistics</category>
    </item>
    <item>
      <title>Taming Divergences in Stan Models</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Mon, 19 Feb 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/martinmodrak/taming-divergences-in-stan-models-5762</link>
      <guid>https://forem.com/martinmodrak/taming-divergences-in-stan-models-5762</guid>
      <description>

&lt;p&gt;Although my time with the &lt;a href="http://mc-stan.org"&gt;Stan language&lt;/a&gt; for statistical computing has been enjoyable, there is one thing that is not fun when modelling with Stan. And it is the dreaded warning message:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;There were X divergent transitions after warmup. 
Increasing adapt_delta above 0.8 may help.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now once you have increased &lt;code&gt;adapt_delta&lt;/code&gt; to no avail, what should you do? Divergences (and max-treedepth and low E-BFMI warnings alike) tell you there is something wrong with your model, but do not exactly tell you what. There are numerous tricks and strategies to diagnose convergence problems, but currently, those are scattered across &lt;a href="http://mc-stan.org/users/documentation/"&gt;Stan documentation&lt;/a&gt;, &lt;a href="http://discourse.mc-stan.org/"&gt;Discourse&lt;/a&gt; and the &lt;a href="https://groups.google.com/forum/#!forum/stan-users"&gt;old mailing list&lt;/a&gt;. Here, I will try to bring all the tricks that helped me at some point to one place for the reference of future desperate modellers.&lt;/p&gt;

&lt;h1&gt;
  
  
  The strategies
&lt;/h1&gt;

&lt;p&gt;I don’t want to keep you waiting, so below is a list of all strategies I have ever used to diagnose and/or remedy divergences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Check your code. Twice. Divergences are almost as likely a result of a programming error as they are a truly statistical issue. Do all parameters have a prior? Do your array indices and for loops match?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a simulated dataset with known true values of all parameters. It is useful for so many things (including checking for coding errors). If the errors disappear on simulated data, your model may be a bad fit for the actual observed data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check your priors. If the model is sampling heavily in the very tails of your priors or on the boundaries of parameter constraints, this is a bad sign.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visualisations: use &lt;code&gt;mcmc_parcoord&lt;/code&gt; from the &lt;a href="https://cran.r-project.org/web/packages/bayesplot/index.html"&gt;&lt;code&gt;bayesplot&lt;/code&gt;&lt;/a&gt; package, &lt;a href="https://cran.r-project.org/web/packages/shinystan/index.html"&gt;Shinystan&lt;/a&gt; and &lt;code&gt;pairs&lt;/code&gt; from &lt;code&gt;rstan&lt;/code&gt;. &lt;a href="http://mc-stan.org/misc/warnings.html#runtime-warnings"&gt;Documentation for Stan Warnings&lt;/a&gt; (contains a few hints), &lt;a href="http://mc-stan.org/users/documentation/case-studies/divergences_and_bias.html"&gt;Case study - diagnosing a multilevel model&lt;/a&gt;, &lt;a href="https://arxiv.org/pdf/1709.01449.pdf"&gt;Gabry et al. 2017 - Visualization in Bayesian workflow&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure your model is &lt;em&gt;identifiable&lt;/em&gt; - non-identifiability and/or multimodality (multiple local maxima of the posterior distributions) is a problem. &lt;a href="http://mc-stan.org/users/documentation/case-studies/identifying_mixture_models.html"&gt;Case study - mixture models&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run Stan with the &lt;code&gt;test_grad&lt;/code&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Reparametrize&lt;/em&gt; your model to make your parameters independent (uncorrelated) and close to N(0,1) (a.k.a change the actual parameters and compute your parameters of interest in the &lt;code&gt;transformed parameters&lt;/code&gt; block).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try &lt;em&gt;non-centered parametrization&lt;/em&gt; - this is a special case of reparametrization that is so frequently useful that it deserves its own bullet. &lt;a href="http://mc-stan.org/users/documentation/case-studies/divergences_and_bias.html"&gt;Case study - diagnosing a multilevel model&lt;/a&gt;, &lt;a href="https://arxiv.org/pdf/1312.0906"&gt;Betancourt &amp;amp; Girolami 2015&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move parameters to the &lt;code&gt;data&lt;/code&gt; block and set them to their true values (from simulated data). Then return them one by one to &lt;code&gt;paremters&lt;/code&gt; block. Which parameter introduces the problems?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce tight priors centered at true parameter values. How tight need the priors to be to let the model fit? Useful for identifying multimodality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Play a bit more with &lt;code&gt;adapt_delta&lt;/code&gt;, &lt;code&gt;stepsize&lt;/code&gt; and &lt;code&gt;max_treedepth&lt;/code&gt;. &lt;a href="http://singmann.org/hierarchical-mpt-in-stan-i-dealing-with-convergent-transitions-via-co%20ntrol-arguments/"&gt;Example&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the coming weeks I hope to be able to provide separate posts on some of the bullets above with a worked-out example. In this introductory post I will try to provide you with some geometric intuition behind what divergences are.&lt;/p&gt;

&lt;h1&gt;
  
  
  Before We Delve In
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; &lt;em&gt;I am not a statistician and my understanding of Stan, the NUTS sampler and other technicalities is limited, so I might be wrong in some of my assertions. Please correct me, if you find mistakes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Make sure to follow &lt;a href="https://github.com/stan-dev/stan/wiki/Stan-Best-Practices"&gt;Stan Best practices&lt;/a&gt;. Especially, &lt;strong&gt;start with a simple model&lt;/strong&gt; , make sure it works and add complexity step by step. I really cannot repeat this enough. To be honest, I often don’t follow this advice myself, because just writing the full model down is so much fun. To be more honest, this has always resulted in me being sad and a lots of wasted time.&lt;/p&gt;

&lt;p&gt;Also note that directly translating models from JAGS/BUGS often fails as Stan requires different modelling approaches. Stan developers have experienced first hand that some JAGS models produce wrong results and do not converge even in JAGS, but no one noticed before they compared their output to results from Stan.&lt;/p&gt;

&lt;h1&gt;
  
  
  What Is a Divergence?
&lt;/h1&gt;

&lt;p&gt;Following the Stan manual:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A divergence arises when the simulated Hamiltonian trajectory departs from the true trajectory as measured by departure of the Hamiltonian value from its initial value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What does that actually mean? Hamiltonian is a function of the posterior density and auxiliary momentum parameters. The auxiliary parameters are well-behaved by construction, so the problem is almost invariably in the posterior density. Keep in mind that for numerical reasons Stan works with the logarithm of posterior density (also known as: &lt;code&gt;log_prob&lt;/code&gt;, &lt;code&gt;__lp&lt;/code&gt; and &lt;code&gt;target&lt;/code&gt;). The NUTS sampler performs several discrete steps per iteration and is guided by the gradient of the density. With some simplification, the sampler assumes that the log density is approximately linear at the current point, i.e. that small change in parameters will result in small change in log-density. This assumption is approximately correct if the step size is small enough. Lets look at two different step sizes in a one-dimensional example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P5HkP7eR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P5HkP7eR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-1-1.png" alt=""&gt;&lt;/a&gt; The sampler starts at the red dot, the black line is the log-density, magenta line is the gradient. When moving 0.1 to the right, the sampler expects the log-density to decrease linearly (green triangle) and although the actual log-density decreases more (the green square), the difference is small. But when moving 0.4 to the right the difference between expected (blue cross) and actual (pink crossed square) becomes much larger. It is a large discrepancy of a similar kind that is signalled as a divergence. During warmup Stan will try to adjust the step size to be small enough for divergences to not occur, but large enough for the sampling to be efficient. But if the parameter space is not well behaved, this might not be possible. Why? Keep on reading, fearless reader.&lt;/p&gt;

&lt;h2&gt;
  
  
  2D Examples
&lt;/h2&gt;

&lt;p&gt;Lets try to build some geometric intuition in 2D parameter space. Keep in mind that sampling is about exploring the parameter space proportionally to the associated posterior density - or, in other words - exploring uniformly across the volume between the zero plane and the surface defined by density (probability mass). For simplicity, we will ignore the log transform Stan actually doeas and talk directly about density in the rest of this post. Imagine the posterior density is a smooth wide hill:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_sezOPLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-2-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_sezOPLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-2-1.png" alt=""&gt;&lt;/a&gt; Stan starts each iteration by moving across the posterior in random direction and then lets the density gradient steer the movement preferrentially to areas with high density. To explore the hill efficiently, we need to take quite large steps in this process - the chain of samples will represent the posterior well if it can move across the whole posterior in a small-ish number of steps (actually at most &lt;code&gt;2^max_treedepth&lt;/code&gt; steps). So average step size of something like 0.1 might be reasonable here as the posterior is approximately linear at this scale. We need to spend a bit more time around the center, but not that much, as there is a lot of volume also close to the edges - it has lower density, but it is a larger area.&lt;/p&gt;

&lt;p&gt;Now imagine that the posterior is much sharper:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gq4gyoEA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-3-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gq4gyoEA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-3-1.png" alt=""&gt;&lt;/a&gt; Now we need much smaller steps to explore safely. Step size of 0.1 won’t work as the posterior is non-linear on this scale, which will result in divergences. The sampler is however able to adapt and chooses a smaller step size accordingly. Another thing Stan will do is to rescale dimensions where the posterior is narrow. In the example above, posterior is narrower in &lt;code&gt;y&lt;/code&gt; and thus this dimension will be inflated to roughly match the spread in &lt;code&gt;x&lt;/code&gt;. Keep in mind that Stan rescales each dimension separately (the posterior is transformed by a diagonal matrix).&lt;/p&gt;

&lt;p&gt;Now what if the posterior is a combination of both a “smooth hill” and a “sharp mountain”?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gy_pkyHg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-4-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gy_pkyHg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-4-1.png" alt=""&gt;&lt;/a&gt; The sampler should spend about half the time in the “sharp mountain” and the other half in the “smooth hill”, but those regions need different step sizes and the sampler only takes one step size. There is also no way to rescale the dimensions to compensate. A chain that adapted to the “smooth hill” region will experience divergences in the “sharp mountain” region, a chain that adapted to the “sharp mountain” will not move efficiently in the “smooth hill” region (which will be signalled as transitions exceeding maximum treedepth). The latter case is however less likely, as the “smooth hill” is larger and chains are more likely to start there. I &lt;em&gt;think&lt;/em&gt; that this is why problems of this kind mostly manifest as divergences and less likely as exceeding maximum treedepth.&lt;/p&gt;

&lt;p&gt;This is only one of many reasons why multimodal posterior hurts sampling. Multimodality is problematic even if all modes are similar - one of the other problems is that traversing between modes might require much larger step size than exploration within each mode, as in this example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hSFb0CaF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-5-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hSFb0CaF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-5-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I bet Stan devs would add tons of other reasons why multimodality is bad for you (it really is), but I’ll stop here and move to other possible sources of divergences.&lt;/p&gt;

&lt;p&gt;The posterior geometry may be problematic, even if it is unimodal. A typical example is a funnel, which often arises in multi-level models:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RL64jcTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-6-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RL64jcTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-6-1.png" alt=""&gt;&lt;/a&gt; Here, the sampler should spend a lot of time near the peak (where it needs small steps), but a non-negligible volume is also found in the relatively low-density but large area on the right where a larger step size is required. Once again, there is no way to rescale each dimension independently to selectively “stretch” the area around the peak. Similar problems also arise with large regions of constant or almost constant density combined with a single mode.&lt;/p&gt;

&lt;p&gt;Last, but not least, lets look at tight correlation between variables, which is a different but frequent problem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iHMJWUgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-7-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iHMJWUgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-7-1.png" alt=""&gt;&lt;/a&gt; The problem is that if we are moving in the direction of the ridge, we need large step size, but when we move tangentially to that direction, we need small step size. Once again, Stan is unable to rescale the posterior to compensate as scaling &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; on its own will increase both width and length of the ridge.&lt;/p&gt;

&lt;p&gt;Things get even more insidious when the relationship between the two variables is not linear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1ZkzLjgK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-8-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1ZkzLjgK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.martinmodrak.cz/post/2018-03-01-strategies-for-diverging-stan-models_files/figure-html/unnamed-chunk-8-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, a good step size is a function of both location (smaller near the peak) and direction (larger when following the spiral) making this kind of posterior hard to sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bigger Picture
&lt;/h2&gt;

&lt;p&gt;This has been all pretty vague and folksy. Remeber these examples are there just to provide intuition. To be 100% correct, you need to go to the &lt;a href="http://www.jmlr.org/papers/volume15/hoffman14a/hoffman14a.pdf"&gt;NUTS paper&lt;/a&gt; and/or the &lt;a href="https://arxiv.org/abs/1701.02434"&gt;Conceptual Introduction to HMC paper&lt;/a&gt; and delve in the math. The math is always correct.&lt;/p&gt;

&lt;p&gt;In particular all the above geometries &lt;strong&gt;may&lt;/strong&gt; be difficult for NUTS and seeing them in visualisations hints at possible issues, but they &lt;strong&gt;may&lt;/strong&gt; also be handled just fine. In fact, I wouldn’t be surprised if Stan worked with almost anything in two dimensions. Weak linear correlations that form wide ridges are also - in my experience - quite likely to be sampled well, even in higher dimensions. The issues arise when regions of non-negligible density are very narrow in some directions and much wider in others and rescaling each dimension individually won’t help. And finally, keep in mind that the posterios we discussed are even more difficult for Gibbs or other older samplers - and Gibbs will not even let you know there was a problem.&lt;/p&gt;

&lt;h1&gt;
  
  
  Love Thy Divergences
&lt;/h1&gt;

&lt;p&gt;The amazing thing about divergences is that what is essentially a numerical problem actually signals a wide array of possibly severe modelling problems. Be glad - few algorithms (in any area) have such a clear signal that things went wrong. This is also the reason why you should be suspicious about your results even when only a single divergence had been reported - you don’t know what is hiding in the parts of your posterior that are inaccessible with the current step size.&lt;/p&gt;

&lt;p&gt;That’s all for now. Hope to see you in the future with examples of actual diverging Stan models.&lt;/p&gt;


</description>
      <category>stan</category>
      <category>bayesianstatistics</category>
      <category>mcmc</category>
    </item>
    <item>
      <title>Launch Shiny App Without Blocking the Session</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Tue, 13 Feb 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/martinmodrak/launch-shiny-app-without-blocking-the-session-3c1p</link>
      <guid>https://forem.com/martinmodrak/launch-shiny-app-without-blocking-the-session-3c1p</guid>
      <description>&lt;p&gt;This is a neat trick I found on &lt;a href="https://twitter.com/tylermorganwall/status/962074911949840387"&gt;Tyler Morgan-Wall’s Twitter&lt;/a&gt; and is originally attributed to &lt;a href="https://twitter.com/jcheng"&gt;Joe Cheng&lt;/a&gt;. You can run any Shiny app without blocking the session. My helper function to run ShinyStan without blocking is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;launch_shinystan_nonblocking &amp;lt;- function(fit) {
  library(future)
  plan(multisession)
  future(
    launch_shinystan(fit) #You can replace this with any other Shiny app
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope that helps!&lt;/p&gt;

</description>
      <category>r</category>
      <category>shiny</category>
      <category>stan</category>
    </item>
    <item>
      <title>A Gentle Stan vs. INLA Comparison</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Fri, 02 Feb 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/martinmodrak/a-gentle-stan-vs-inla-comparison-2nl5</link>
      <guid>https://forem.com/martinmodrak/a-gentle-stan-vs-inla-comparison-2nl5</guid>
      <description>

&lt;p&gt;&lt;em&gt;I have recently become a huge fan of Bayesian statistics. It makes so much sense and if you are doing any kind of inferences from data, you should check it out, especially the &lt;a href="http://mc-stan.org/"&gt;Stan language&lt;/a&gt;. Without much further intro, this is my first blog on statistical topics.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not long ago, I came across a nice blogpost by Kahtryn Morrison called &lt;a href="https://www.precision-analytics.ca/blog-1/inla"&gt;A gentle INLA tutorial&lt;/a&gt;. The blog was nice and helped me better appreciate INLA. But as a fan of the Stan probabilistic language, I felt that comparing INLA to JAGS is not really that relevant, as Stan should - at least in theory - be way faster and better than JAGS. Here, I ran a comparison of INLA to Stan on the second example called “Poisson GLM with an iid random effect”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The TLDR is:&lt;/strong&gt; For this model, Stan scales considerably better than JAGS, but still cannot scale to very large model. Also, for this model Stan and INLA give almost the same results. It seems that Stan becomes useful only when your model cannot be coded in INLA.&lt;/p&gt;

&lt;p&gt;Pleas let me know (via an &lt;a href="https://github.com/martinmodrak/blog/issues"&gt;issue on GitHub&lt;/a&gt;) should you find any error or anything else that should be included in this post. Also, if you run the experiment on a different machine and/or with different seed, let me know the results.&lt;/p&gt;

&lt;p&gt;Here are the original numbers from Kathryn’s blog:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;kathryn_rjags&lt;/th&gt;
&lt;th&gt;kathryn_rinla&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;30.394&lt;/td&gt;
&lt;td&gt;0.383&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;142.532&lt;/td&gt;
&lt;td&gt;1.243&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5000&lt;/td&gt;
&lt;td&gt;1714.468&lt;/td&gt;
&lt;td&gt;5.768&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25000&lt;/td&gt;
&lt;td&gt;8610.32&lt;/td&gt;
&lt;td&gt;30.077&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100000&lt;/td&gt;
&lt;td&gt;got bored after 6 hours&lt;/td&gt;
&lt;td&gt;166.819&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Full source of this post is available at &lt;a href="https://github.com/martinmodrak/blog/blob/master/content/post/2018-02-02-stan-vs-inla.Rmd"&gt;this blog’s Github repo&lt;/a&gt;. Keep in mind that installing RStan is unfortunately not as straightforward as running install.packages. Please consult &lt;a href="https://github.com/stan-dev/rstan/wiki/RStan-Getting-Started"&gt;https://github.com/stan-dev/rstan/wiki/RStan-Getting-Started&lt;/a&gt; if you don’t have RStan already installed.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;

&lt;p&gt;The model we are interested in is a simple GLM with partial pooling of a random effect:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y_i ~ poisson(mu_i)
log(mu_i) ~ alpha + beta * x_i + nu_i
nu_i ~ normal(0, tau_nu)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  The comparison
&lt;/h2&gt;

&lt;p&gt;Let’s setup our libraries.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library(rstan)
library(brms)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())
library(INLA)
library(tidyverse)
set.seed(6619414)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The results are stored in files within the repository to let me rebuild the site with blogdown easily. Delete cache directory to force a complete rerun.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache_dir = "_stan_vs_inla_cache/"
if(!dir.exists(cache_dir)){
  dir.create(cache_dir)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s start by simulating data&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#The sizes of datasets to work with
N_values = c(100, 500, 5000, 25000)
data = list()
for(N in N_values) {
  x = rnorm(N, mean=5,sd=1) 
  nu = rnorm(N,0,0.1)
  mu = exp(1 + 0.5*x + nu) 
  y = rpois(N,mu) 


  data[[N]] = list(
    N = N,
    x = x,
    y = y
  )  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Measuring Stan
&lt;/h3&gt;

&lt;p&gt;Here is the model code in Stan (it is good practice to put it into a file, but I wanted to make this post self-contained). It is almost 1-1 rewrite of the original JAGS code, with few important changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JAGS parametrizes normal distribution via precision, Stan via sd. The model recomputes precision to sd.&lt;/li&gt;
&lt;li&gt;I added the ability to explicitly set parameters of the prior distributions as data which is useful later in this post&lt;/li&gt;
&lt;li&gt;With multilevel models, Stan works waaaaaay better with so-called non-centered parametrization. This means that instead of having &lt;code&gt;nu ~ N(0, nu_sigma), mu = alpha + beta * x + nu&lt;/code&gt; we have &lt;code&gt;nu_normalized ~ N(0,1), mu = alpha + beta * x + nu_normalized * nu_sigma&lt;/code&gt;. This gives exactly the same inferences, but results in a geometry that Stan can explore efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also packages to let you specify common models (including this one) without writing Stan code, using syntax similar to R-INLA - checkout &lt;a href="http://mc-stan.org/users/interfaces/rstanarm"&gt;rstanarm&lt;/a&gt; and &lt;a href="https://cran.r-project.org/web/packages/brms/index.html"&gt;brms&lt;/a&gt;. The latter is more flexible, while the former is easier to install, as it does not depend on rstan and can be installed simply with &lt;code&gt;install.packages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note also that Stan developers would suggest against Gamma(0.01,0.01) prior on precision in favor of normal or Cauchy distribution on sd, see &lt;a href="https://github.com/stan-dev/stan/wiki/Prior-Choice-Recommendations"&gt;https://github.com/stan-dev/stan/wiki/Prior-Choice-Recommendations&lt;/a&gt;.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight mosel"&gt;&lt;code&gt;&lt;span class="n"&gt;model_code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"
  data {
    int N;
    vector[N] x;
    int y[N];

    //Allowing to parametrize the priors (useful later)
    real alpha_prior_mean;
    real beta_prior_mean;
    real&amp;lt;lower=0&amp;gt; alpha_beta_prior_precision;
    real&amp;lt;lower=0&amp;gt; tau_nu_prior_shape;
    real&amp;lt;lower=0&amp;gt; tau_nu_prior_rate; 
  }

  transformed data {
    //Stan parametrizes normal with sd not precision
    real alpha_beta_prior_sigma = sqrt(1 / alpha_beta_prior_precision);
  }

  parameters {
    real alpha;
    real beta;
    vector[N] nu_normalized;
    real&amp;lt;lower=0&amp;gt; tau_nu;
  }

  model {
    real nu_sigma = sqrt(1 / tau_nu);
    vector[N] nu = nu_normalized * nu_sigma;

    //taking advantage of Stan's implicit vectorization here
    nu_normalized ~ normal(0,1);
    //The built-in poisson_log(x) === poisson(exp(x))
    y ~ poisson_log(alpha + beta*x + nu); 

    alpha ~ normal(alpha_prior_mean, alpha_beta_prior_sigma);
    beta ~ normal(beta_prior_mean, alpha_beta_prior_sigma); 
    tau_nu ~ gamma(tau_nu_prior_shape,tau_nu_prior_rate);
  }

//Uncomment this to have the model generate mu values as well
//Currently commented out as storing the samples of mu consumes 
//a lot of memory for the big models
/*  
  generated quantities {
    vector[N] mu = exp(alpha + beta*x + nu_normalized * nu_sigma);
  }
*/
"&lt;/span&gt;

&lt;span class="k"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stan_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_code&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Below is the code to make the actual measurements. Some caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The compilation of the Stan model is not counted (you can avoid it with rstanarm and need to do it only once otherwise)&lt;/li&gt;
&lt;li&gt;There is some overhead in transferring the posterior samples from Stan to R. This overhead is non-negligible for the larger models, but you can get rid of it by storing the samples in a file and reading them separately. The overhead is not measured here.&lt;/li&gt;
&lt;li&gt;Stan took &amp;gt; 16 hours to converge for the largest data size (1e5) and then I had issues fitting the posterior samples into memory on my computer. Notably, R-Inla also crashed on my computer for this size. The largest size is thus excluded here, but I have to conclude that if you get bored after 6 hours, Stan is not practical for such a big model.&lt;/li&gt;
&lt;li&gt;I was not able to get rjags running in a reasonable amount of time, so I did not rerun the JAGS version of the model.&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stan_times_file = paste0(cache_dir, "stan_times.csv")
stan_summary_file = paste0(cache_dir, "stan_summary.csv")
run_stan = TRUE
if(file.exists(stan_times_file) &amp;amp;&amp;amp; file.exists(stan_summary_file)) {
  stan_times = read.csv(stan_times_file)
  stan_summary = read.csv(stan_summary_file) 
  if(setequal(stan_times$N, N_values) &amp;amp;&amp;amp; setequal(stan_summary$N, N_values)) {
    run_stan = FALSE
  }
} 

if(run_stan) {
  stan_times_values = numeric(length(N_values))
  stan_summary_list = list()
  step = 1
  for(N in N_values) {
    data_stan = data[[N]]
    data_stan$alpha_prior_mean = 0
    data_stan$beta_prior_mean = 0
    data_stan$alpha_beta_prior_precision = 0.001
    data_stan$tau_nu_prior_shape = 0.01
    data_stan$tau_nu_prior_rate = 0.01


    fit = sampling(model, data = data_stan);
    stan_summary_list[[step]] = 
      as.data.frame(
        rstan::summary(fit, pars = c("alpha","beta","tau_nu"))$summary
      ) %&amp;gt;% rownames_to_column("parameter")
    stan_summary_list[[step]]$N = N

    all_times = get_elapsed_time(fit)
    stan_times_values[step] = max(all_times[,"warmup"] + all_times[,"sample"])

    step = step + 1
  }
  stan_times = data.frame(N = N_values, stan_time = stan_times_values)
  stan_summary = do.call(rbind, stan_summary_list)

  write.csv(stan_times, stan_times_file,row.names = FALSE)
  write.csv(stan_summary, stan_summary_file,row.names = FALSE)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Measuring INLA
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inla_times_file = paste0(cache_dir,"inla_times.csv")
inla_summary_file = paste0(cache_dir,"inla_summary.csv")
run_inla = TRUE
if(file.exists(inla_times_file) &amp;amp;&amp;amp; file.exists(inla_summary_file)) {
  inla_times = read.csv(inla_times_file)
  inla_summary = read.csv(inla_summary_file) 
  if(setequal(inla_times$N, N_values) &amp;amp;&amp;amp; setequal(inla_summary$N, N_values)) {
    run_inla = FALSE
  }
} 

if(run_inla) {
  inla_times_values = numeric(length(N_values))
  inla_summary_list = list()
  step = 1
  for(N in N_values) {
    nu = 1:N 
    fit_inla = inla(y ~ x + f(nu,model="iid"), family = c("poisson"), 
               data = data[[N]], control.predictor=list(link=1)) 

    inla_times_values[step] = fit_inla$cpu.used["Total"]
    inla_summary_list[[step]] = 
      rbind(fit_inla$summary.fixed %&amp;gt;% select(-kld),
            fit_inla$summary.hyperpar) %&amp;gt;% 
      rownames_to_column("parameter")
    inla_summary_list[[step]]$N = N

    step = step + 1
  }
  inla_times = data.frame(N = N_values, inla_time = inla_times_values)
  inla_summary = do.call(rbind, inla_summary_list)

  write.csv(inla_times, inla_times_file,row.names = FALSE)
  write.csv(inla_summary, inla_summary_file,row.names = FALSE)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Checking inferences
&lt;/h3&gt;

&lt;p&gt;Here we see side-by-side comparisons of the inferences and they seem pretty comparable between Stan and Inla:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for(N_to_show in N_values) {
  print(kable(stan_summary %&amp;gt;% filter(N == N_to_show) %&amp;gt;% 
                select(c("parameter","mean","sd")), 
              caption = paste0("Stan results for N = ", N_to_show)))
  print(kable(inla_summary %&amp;gt;% filter(N == N_to_show) %&amp;gt;% 
                select(c("parameter","mean","sd")), 
              caption = paste0("INLA results for N = ", N_to_show)))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;Stan results for N = 100| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| alpha | 1.013559 | 0.0989778 |&lt;br&gt;
| beta | 0.495539 | 0.0176988 |&lt;br&gt;
| tau_nu | 162.001608 | 82.7700473 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;INLA results for N = 100| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| (Intercept) | 1.009037e+00 | 9.15248e-02 |&lt;br&gt;
| x | 4.971302e-01 | 1.61486e-02 |&lt;br&gt;
| Precision for nu | 1.819654e+04 | 1.71676e+04 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;Stan results for N = 500| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| alpha | 1.0046284 | 0.0555134 |&lt;br&gt;
| beta | 0.4977522 | 0.0102697 |&lt;br&gt;
| tau_nu | 71.6301530 | 13.8264812 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;INLA results for N = 500| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| (Intercept) | 1.0053202 | 0.0538456 |&lt;br&gt;
| x | 0.4977124 | 0.0099593 |&lt;br&gt;
| Precision for nu | 77.3311793 | 16.0255430 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;Stan results for N = 5000| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| alpha | 1.009930 | 0.0159586 |&lt;br&gt;
| beta | 0.496859 | 0.0029250 |&lt;br&gt;
| tau_nu | 101.548580 | 7.4655716 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;INLA results for N = 5000| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| (Intercept) | 1.0099282 | 0.0155388 |&lt;br&gt;
| x | 0.4968718 | 0.0028618 |&lt;br&gt;
| Precision for nu | 103.1508773 | 7.6811740 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;Stan results for N = 25000| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| alpha | 0.9874707 | 0.0066864 |&lt;br&gt;
| beta | 0.5019566 | 0.0012195 |&lt;br&gt;
| tau_nu | 104.3599424 | 3.5391938 |


&lt;br&gt;
&lt;span id="tab:unnamed-chunk-6"&gt;Table 1: &lt;/span&gt;INLA results for N = 25000| parameter | mean | sd |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| (Intercept) | 0.9876218 | 0.0067978 |&lt;br&gt;
| x | 0.5019341 | 0.0012452 |&lt;br&gt;
| Precision for nu | 104.8948949 | 3.4415929 |
&lt;h3&gt;
  
  
  Summary of the timing
&lt;/h3&gt;

&lt;p&gt;You can see that Stan keeps reasonable runtimes for longer time than JAGS in the original blog post, but INLA is still way faster. Also Kathryn got probably very lucky with her seed for N = 25 000, as her INLA run completed very quickly. With my (few) tests, INLA always took at least several minutes for N = 25 000. It may mean that Kathryn’s JAGS time is also too short.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_results = merge.data.frame(inla_times, stan_times, by = "N")
kable(merge.data.frame(my_results, kathryn_results, by = "N"))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;inla_time&lt;/th&gt;
&lt;th&gt;stan_time&lt;/th&gt;
&lt;th&gt;kathryn_rjags&lt;/th&gt;
&lt;th&gt;kathryn_rinla&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;1.061742&lt;/td&gt;
&lt;td&gt;1.885&lt;/td&gt;
&lt;td&gt;30.394&lt;/td&gt;
&lt;td&gt;0.383&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;1.401597&lt;/td&gt;
&lt;td&gt;11.120&lt;/td&gt;
&lt;td&gt;142.532&lt;/td&gt;
&lt;td&gt;1.243&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5000&lt;/td&gt;
&lt;td&gt;10.608704&lt;/td&gt;
&lt;td&gt;388.514&lt;/td&gt;
&lt;td&gt;1714.468&lt;/td&gt;
&lt;td&gt;5.768&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25000&lt;/td&gt;
&lt;td&gt;611.505543&lt;/td&gt;
&lt;td&gt;5807.670&lt;/td&gt;
&lt;td&gt;8610.32&lt;/td&gt;
&lt;td&gt;30.077&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You could obviously do multiple runs to reduce uncertainty etc., but this post has already taken too much time of mine, so this will be left to others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing quality of the results
&lt;/h2&gt;

&lt;p&gt;I also had a hunch that maybe INLA is less precise than Stan, but that turned out to be based on an error. Thus, without much commentary, I put here my code to test this. Basically, I modify the random data generator to actually draw from priors (those priors are quite constrained to provide similar values of alpha, beta nad tau_nu as in the original). I than give both algorithms the knowledge of these priors. I compute both difference between true parameters and a point estimate (mean) and quantiles of the posterior distribution where the true parameter is found. If the algorithms give the best possible estimates, the distribution of such quantiles should be uniform over (0,1). Turns out INLA and Stan give almost exactly the same results for almost all runs and the differences in quality are (for this particular model) negligible.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test_precision = function(N) {
  rejects &amp;lt;- 0
  repeat {
    #Set the priors so that they generate similar parameters as in the example above

    alpha_beta_prior_precision = 5
    prior_sigma = sqrt(1/alpha_beta_prior_precision)
    alpha_prior_mean = 1
    beta_prior_mean = 0.5
    alpha = rnorm(1, alpha_prior_mean, prior_sigma)
    beta = rnorm(1, beta_prior_mean, prior_sigma)

    tau_nu_prior_shape = 2
    tau_nu_prior_rate = 0.01
    tau_nu = rgamma(1,tau_nu_prior_shape,tau_nu_prior_rate)
    sigma_nu = sqrt(1 / tau_nu)

    x = rnorm(N, mean=5,sd=1) 


    nu = rnorm(N,0,sigma_nu)
    linear = alpha + beta*x + nu

    #Rejection sampling to avoid NAs and ill-posed problems
    if(max(linear) &amp;lt; 15) {
      mu = exp(linear) 
      y = rpois(N,mu) 
      if(mean(y == 0) &amp;lt; 0.7) {
        break;
      }
    } 
    rejects = rejects + 1
  }

  #cat(rejects, "rejects\n")


  data = list(
    N = N,
    x = x,
    y = y
  )
  #cat("A:",alpha,"B:", beta, "T:", tau_nu,"\n")
  #print(linear)
  #print(data)

  #=============== Fit INLA
  nu = 1:N 
  fit_inla = inla(y ~ x + f(nu,model="iid",
                  hyper=list(theta=list(prior="loggamma",
                                        param=c(tau_nu_prior_shape,tau_nu_prior_rate)))), 
                  family = c("poisson"), 
                  control.fixed = list(mean = beta_prior_mean, 
                                       mean.intercept = alpha_prior_mean,
                                       prec = alpha_beta_prior_precision,
                                       prec.intercept = alpha_beta_prior_precision
                                       ),
             data = data, control.predictor=list(link=1)
             ) 

  time_inla = fit_inla$cpu.used["Total"]

  alpha_mean_diff_inla = fit_inla$summary.fixed["(Intercept)","mean"] - alpha
  beta_mean_diff_inla = fit_inla$summary.fixed["x","mean"] - beta
  tau_nu_mean_diff_inla = fit_inla$summary.hyperpar[,"mean"] - tau_nu

  alpha_q_inla = inla.pmarginal(alpha, fit_inla$marginals.fixed$`(Intercept)`)
  beta_q_inla = inla.pmarginal(beta, fit_inla$marginals.fixed$x)
  tau_nu_q_inla = inla.pmarginal(tau_nu, fit_inla$marginals.hyperpar$`Precision for nu`)



  #================ Fit Stan
  data_stan = data
  data_stan$alpha_prior_mean = alpha_prior_mean
  data_stan$beta_prior_mean = beta_prior_mean
  data_stan$alpha_beta_prior_precision = alpha_beta_prior_precision
  data_stan$tau_nu_prior_shape = tau_nu_prior_shape
  data_stan$tau_nu_prior_rate = tau_nu_prior_rate

  fit = sampling(model, data = data_stan, control = list(adapt_delta = 0.95)); 
  all_times = get_elapsed_time(fit)
  max_total_time_stan = max(all_times[,"warmup"] + all_times[,"sample"])

  samples = rstan::extract(fit, pars = c("alpha","beta","tau_nu"))
  alpha_mean_diff_stan = mean(samples$alpha) - alpha
  beta_mean_diff_stan = mean(samples$beta) - beta
  tau_nu_mean_diff_stan = mean(samples$tau_nu) - tau_nu

  alpha_q_stan = ecdf(samples$alpha)(alpha)
  beta_q_stan = ecdf(samples$beta)(beta)
  tau_nu_q_stan = ecdf(samples$tau_nu)(tau_nu)

  return(data.frame(time_rstan = max_total_time_stan,
                    time_rinla = time_inla,
                    alpha_mean_diff_stan = alpha_mean_diff_stan,
                    beta_mean_diff_stan = beta_mean_diff_stan,
                    tau_nu_mean_diff_stan = tau_nu_mean_diff_stan,
                    alpha_q_stan = alpha_q_stan,
                    beta_q_stan = beta_q_stan,
                    tau_nu_q_stan = tau_nu_q_stan,
                    alpha_mean_diff_inla = alpha_mean_diff_inla,
                    beta_mean_diff_inla = beta_mean_diff_inla,
                    tau_nu_mean_diff_inla = tau_nu_mean_diff_inla,
                    alpha_q_inla= alpha_q_inla,
                    beta_q_inla = beta_q_inla,
                    tau_nu_q_inla = tau_nu_q_inla
                    ))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Actually running the comparison. On some occasions, Stan does not converge, my best guess is that the data are somehow pathological, but I didn’t investigate thoroughly. You see that results for Stan and Inla are very similar both as point estimates and the distribution of posterior quantiles. The accuracy of the INLA approximation is also AFAIK going to improve with more data.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library(skimr) #Uses skimr to summarize results easily
precision_results_file = paste0(cache_dir,"precision_results.csv")
if(file.exists(precision_results_file)) {
  results_precision_df = read.csv(precision_results_file)
} else {
  results_precision = list()
  for(i in 1:100) {
    results_precision[[i]] = test_precision(50)
  }

  results_precision_df = do.call(rbind, results_precision)
  write.csv(results_precision_df,precision_results_file,row.names = FALSE)
}

#Remove uninteresting skim statistics
skim_with(numeric = list(missing = NULL, complete = NULL, n = NULL))

skimmed = results_precision_df %&amp;gt;% select(-X) %&amp;gt;% skim() 
#Now a hack to display skim histograms properly in the output:
skimmed_better = skimmed %&amp;gt;% rowwise() %&amp;gt;% mutate(formatted = 
     if_else(stat == "hist", 
         utf8ToInt(formatted) %&amp;gt;% as.character() %&amp;gt;% paste0("&amp;amp;#", . ,";", collapse = ""), 
         formatted))  
mostattributes(skimmed_better) = attributes(skimmed)

skimmed_better %&amp;gt;% kable(escape = FALSE)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Skim summary statistics&lt;br&gt;&lt;br&gt;
n obs: 100&lt;br&gt;&lt;br&gt;
n variables: 14&lt;/p&gt;

&lt;p&gt;Variable type: numeric&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;variable&lt;/th&gt;
&lt;th&gt;mean&lt;/th&gt;
&lt;th&gt;sd&lt;/th&gt;
&lt;th&gt;p0&lt;/th&gt;
&lt;th&gt;p25&lt;/th&gt;
&lt;th&gt;p50&lt;/th&gt;
&lt;th&gt;p75&lt;/th&gt;
&lt;th&gt;p100&lt;/th&gt;
&lt;th&gt;hist&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;alpha_mean_diff_inla&lt;/td&gt;
&lt;td&gt;-0.0021&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;-0.85&lt;/td&gt;
&lt;td&gt;-0.094&lt;/td&gt;
&lt;td&gt;0.0023&lt;/td&gt;
&lt;td&gt;0.095&lt;/td&gt;
&lt;td&gt;0.53&lt;/td&gt;
&lt;td&gt;▁▁▁▂▇▇▁▁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;alpha_mean_diff_stan&lt;/td&gt;
&lt;td&gt;-0.0033&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;-0.84&lt;/td&gt;
&lt;td&gt;-0.097&lt;/td&gt;
&lt;td&gt;-0.00012&lt;/td&gt;
&lt;td&gt;0.093&lt;/td&gt;
&lt;td&gt;0.52&lt;/td&gt;
&lt;td&gt;▁▁▁▂▇▇▁▂&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;alpha_q_inla&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;0.29&lt;/td&gt;
&lt;td&gt;0.00084&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;▅▇▇▆▇▆▆▇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;alpha_q_stan&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;0.28&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;td&gt;0.26&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;▅▇▇▆▇▆▆▇&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;beta_mean_diff_inla&lt;/td&gt;
&lt;td&gt;-0.00088&lt;/td&gt;
&lt;td&gt;0.04&lt;/td&gt;
&lt;td&gt;-0.12&lt;/td&gt;
&lt;td&gt;-0.016&lt;/td&gt;
&lt;td&gt;-0.001&lt;/td&gt;
&lt;td&gt;0.014&lt;/td&gt;
&lt;td&gt;0.17&lt;/td&gt;
&lt;td&gt;▁▁▃▇▂▁▁▁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;beta_mean_diff_stan&lt;/td&gt;
&lt;td&gt;-0.001&lt;/td&gt;
&lt;td&gt;0.04&lt;/td&gt;
&lt;td&gt;-0.12&lt;/td&gt;
&lt;td&gt;-0.016&lt;/td&gt;
&lt;td&gt;-5e-04&lt;/td&gt;
&lt;td&gt;0.014&lt;/td&gt;
&lt;td&gt;0.16&lt;/td&gt;
&lt;td&gt;▁▁▂▇▂▁▁▁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;beta_q_inla&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;td&gt;0.28&lt;/td&gt;
&lt;td&gt;0.0068&lt;/td&gt;
&lt;td&gt;0.26&lt;/td&gt;
&lt;td&gt;0.52&lt;/td&gt;
&lt;td&gt;0.75&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;▆▆▅▆▇▅▆▆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;beta_q_stan&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;td&gt;0.28&lt;/td&gt;
&lt;td&gt;0.0065&lt;/td&gt;
&lt;td&gt;0.27&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;td&gt;0.75&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;▆▆▅▇▆▅▆▆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tau_nu_mean_diff_inla&lt;/td&gt;
&lt;td&gt;4.45&lt;/td&gt;
&lt;td&gt;90.17&lt;/td&gt;
&lt;td&gt;-338.58&lt;/td&gt;
&lt;td&gt;-26.74&lt;/td&gt;
&lt;td&gt;4.49&lt;/td&gt;
&lt;td&gt;53.38&lt;/td&gt;
&lt;td&gt;193&lt;/td&gt;
&lt;td&gt;▁▁▁▂▅▇▃▂&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tau_nu_mean_diff_stan&lt;/td&gt;
&lt;td&gt;5.21&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;-339.89&lt;/td&gt;
&lt;td&gt;-24.62&lt;/td&gt;
&lt;td&gt;4.29&lt;/td&gt;
&lt;td&gt;54.48&lt;/td&gt;
&lt;td&gt;191.94&lt;/td&gt;
&lt;td&gt;▁▁▁▂▅▇▃▂&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tau_nu_q_inla&lt;/td&gt;
&lt;td&gt;0.53&lt;/td&gt;
&lt;td&gt;0.26&lt;/td&gt;
&lt;td&gt;0.023&lt;/td&gt;
&lt;td&gt;0.32&lt;/td&gt;
&lt;td&gt;0.52&lt;/td&gt;
&lt;td&gt;0.74&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;▃▅▆▆▇▆▅▅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tau_nu_q_stan&lt;/td&gt;
&lt;td&gt;0.53&lt;/td&gt;
&lt;td&gt;0.26&lt;/td&gt;
&lt;td&gt;0.021&lt;/td&gt;
&lt;td&gt;0.32&lt;/td&gt;
&lt;td&gt;0.53&lt;/td&gt;
&lt;td&gt;0.75&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;▃▅▅▆▇▃▅▅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;time_rinla&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;0.093&lt;/td&gt;
&lt;td&gt;0.86&lt;/td&gt;
&lt;td&gt;0.91&lt;/td&gt;
&lt;td&gt;0.93&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;1.32&lt;/td&gt;
&lt;td&gt;▇▇▂▁▁▁▁▁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;time_rstan&lt;/td&gt;
&lt;td&gt;1.79&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;0.55&lt;/td&gt;
&lt;td&gt;0.89&lt;/td&gt;
&lt;td&gt;1.45&lt;/td&gt;
&lt;td&gt;2.09&lt;/td&gt;
&lt;td&gt;10.04&lt;/td&gt;
&lt;td&gt;▇▂▁▁▁▁▁▁&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


</description>
      <category>r</category>
      <category>bayesianstatistics</category>
      <category>stan</category>
      <category>inla</category>
    </item>
    <item>
      <title>What Elm and Rust Teach us About the Future</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Wed, 08 Feb 2017 08:07:49 +0000</pubDate>
      <link>https://forem.com/martinmodrak/what-elm-and-rust-teach-us-about-the-future</link>
      <guid>https://forem.com/martinmodrak/what-elm-and-rust-teach-us-about-the-future</guid>
      <description>

&lt;p&gt;So I recently started programming in Elm and also did some stuff in Rust. Honestly, it was mostly a hype-driven decision, but the journey was definitely worth it. I also noticed that although those two languages differ in their target audience and use cases, they made many similar design decisions. I think this is no coincidence. It is well possible that ten years from now, both Elm and Rust will be forgotten, but I am quite sure that the ideas they are built upon will be present in the languages we will use by then. This is a post about the ideas I find charming in Elm and Rust.&lt;/p&gt;

&lt;p&gt;A quick disclaimer first: I am no expert in either language and while I am starting to feel comfortable in Elm, I am undoubtedly a Rust beginner, so please correct me if I am doing injustice to any of the languages.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting the Scene
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.rust-lang.org"&gt;Rust&lt;/a&gt; is a systems language which aims to compete with C++. Rust values performance, concurrency, and memory safety, but is not garbage-collected. Rust compiles to native binaries, not only for the major x86/x64 platforms but also on ARM and even certain ARM-based microcontrollers.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://elm-lang.org/"&gt;Elm&lt;/a&gt; is a language for web apps competing with Javascript in general and the virtual DOM frameworks in particular (e.g. ReactJS). Elm compiles to Javascript, is garbage collected and purely functional. Elm values simplicity and reliability.&lt;/p&gt;

&lt;p&gt;Both languages are already usable for actual projects, but the ecosystems are still immature and the languages themselves are still evolving.&lt;/p&gt;

&lt;p&gt;While I like both of the languages, I do not intend to limit this post to the positive sides and will also mention what are (to me) the pain points.&lt;br&gt;
I will start with the ideas the languages have in common, and will give more details about either language later.&lt;/p&gt;

&lt;h1&gt;
  
  
  Common Themes
&lt;/h1&gt;

&lt;p&gt;The features described here are mostly nothing completely new and could be found in languages like OCaml, Haskell and F#. The interesting part is that Elm and Rust prove they are useful for quite diverse use-cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tagged unions
&lt;/h2&gt;

&lt;p&gt;This is a small but very practical feature - I would say tagged unions are enums on steroids. Consider, how often did you write something like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum AccountType {Savings, CreditCard};     

//In real code please use Decimal types to represent money. Please.
class CreditParams {
    int creditLimit; 
    ...
}

class Account {
    AccountType accountType;
    int balance;
    CreditParams creditParams; //only present for CreditCard, always null for Savings       
}       
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This makes room for some sweet bugs, as your data model can represent a state that should be impossible (savings account with non-null credit parameters, or a credit card account with null credit parameters). The programmer needs to take care that no manipulation of the &lt;code&gt;Account&lt;/code&gt; object can lead to such a state which may be non-trivial and error-prone. It also creates ambiguity - for example, there are multiple ways to get the credit limit of an account:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Yes I know, this should be a class method
int getCreditLimit1(Account account) {
    if (account.creditParams != null) { 
        //wrong if account.accountType == Savings
        return account.creditParams.creditLimit;
    } else {
        return 0;
    }
}

int getCreditLimit2(Account account) {
    if (account.accountType == CreditCard) { 
        //possibly accessing a null pointer
        return account.creditParams.creditLimit; 
    } else {
        return 0;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A more desirable option is to &lt;a href="https://medium.com/elm-shorts/how-to-make-impossible-states-impossible-c12a07e907b5#.rbysmekjt"&gt;make impossible states impossible&lt;/a&gt;. Tagged unions let you do this by attaching heterogenous data to each variant. This lets us rewrite the data model as (Rust syntax, &lt;a href="https://is.gd/GSoO8n"&gt;try it online&lt;/a&gt;):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

struct CreditParams {
    credit_limit: i32, //i32 is a 32bit signed int
    ...
} 

enum AccountDetails {
    Savings, //Savings has no attached data
    CreditCard(CreditParams), //CreditCard has a single CreditParams instance
}

struct Account { 
    balance: i32, 
    details: AccountDetails,
  }

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With tagged unions, you cannot access the attached data without explicitly checking the type - so there is only one way to get the credit limit and it is always correct (Rust syntax, &lt;a href="https://is.gd/GSoO8n"&gt;try it online&lt;/a&gt;):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn get_credit_limit(account: Account) -&amp;gt; i32 {
    match account.details { //match is like case
        AccountDetails::CreditCard(params) =&amp;gt;  //bind local variable params to the attached data
            params.credit_limit,    //in Rust, return is implicit
        AccountDetails::Savings =&amp;gt; 
            0
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since both Elm and Rust don't have null values, you have to specify &lt;code&gt;CreditParams&lt;/code&gt; when building an &lt;code&gt;AccountDetails&lt;/code&gt; instance, and so the code above is safe in all situations.&lt;/p&gt;

&lt;p&gt;A further bonus is that in both Elm and Rust, you have to handle all possible cases of a tagged union (or provide a default branch). Failing to handle all cases is a compile-time error. In this way, the compiler makes sure that you update all your code when you extend the &lt;code&gt;AcountDetails&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type Inference
&lt;/h2&gt;

&lt;p&gt;Some people are fond of static typing as it is harder to write erroneous code in statically-typed languages. Some poeple like dynamic typing, because it avoids the bureacracy of adding type annotations to everything. Type inference tries to get the best of both worlds: the language is statically typed, but you rarely need to provide type annotations. Type inference in Rust and Elm works a bit like &lt;code&gt;auto&lt;/code&gt; in C++, but it is much more powerful - it looks at broader context and takes also downstream code into consideration. So for example (Rust syntax, &lt;a href="https://is.gd/izOGxZ"&gt;try it online&lt;/a&gt;)&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The compiler infers that elem is a float.
let elem = 1.36;

//Explicit type annotation - f64 is a double precision float
let elem2: f64 = 3.141592;

// Create an empty vector (a growable array).
let mut vec = Vec::new();
// At this point the compiler doesn't know the exact type of `vec`, it
// just knows that it's a vector of something (`Vec&amp;lt;_&amp;gt;`).

// Insert `elem` and `elem2` in the vector.
vec.push(elem);
vec.push(elem2);
// Aha! Now the compiler knows that `vec` is a vector of doubles (`Vec&amp;lt;f64&amp;gt;`)

//The compiler infers that s is a &amp;amp;str (reference to string)
let s = "Hello";

//Compile-time error: expected floating-point variable, found &amp;amp;str
vec.push(s); 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Type inference in Rust has certain limitations and so explicit type annotations are still needed now and then. But Elm goes further, implementing a variant of the &lt;a href="https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system"&gt;Hindley-Milner type system&lt;/a&gt;. In practice this means that type annotations in Elm are basically just comments (except some &lt;a href="https://github.com/elm-lang/elm-compiler/issues/1353"&gt;weird corner cases&lt;/a&gt;). While the Elm compiler enforces that type annotations match the code, they can be omitted and the compiler will still statically typecheck everything. Nevertheless, it is a warning to not annotate your functions with types, as type annotations let the compiler give you better error messages and force you to articulate your intent clearly. &lt;/p&gt;

&lt;h2&gt;
  
  
  Immutability
&lt;/h2&gt;

&lt;p&gt;Immutability means that variables/data cannot be modified after initial assignment/creation. Another way to state it is that operations on immutable data can have no observable effect except for returning a value. This implies that functions on immutable data will always return the same value for the same arguments. Code working with immutable data is  easier to understand and reason about and is inherently thread-safe. Consider this code with mutable data:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;address = new Address();
address.street = "Mullholland Drive";
...
person = new Person();
person.primaryAddress = address;
print(person.primaryAddress.street) //Mullholland Drive
...
address.street = "Park Avenue"
...
print(person.primaryAddress.street) //Park Avenue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let's say we want to figure out why &lt;code&gt;person.primaryAddress.street&lt;/code&gt; changed. Since the data is mutable, it is not sufficient to find all usages of &lt;code&gt;person.primaryAddress&lt;/code&gt; - we also need to check the whole tree of all variables/fields that were assigned to/from &lt;code&gt;person.primaryAddress&lt;/code&gt;. With immutable data structures this problem is prevented as the programmer is forced to write something like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;address = new Address("Mullholland Drive", 1035, "California");
//Elm and Rust also support syntax of the form:
//address = { street = "Mullholland Drive", number = 1035, state = "California" }
...
person = new Person(address);
...
address.street = "Park Avenue" //not allowed, the object is immutable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For a more detailed discussion of why immutability is good, see for example &lt;a href="https://dev.to/0x13a/3-benefits-of-using-immutable-objects"&gt;3 benefits of using Immutable Objects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Elm goes all-in on immutability - everything is immutable and no function can have a side effect. Rust is a bit more relaxed: in Rust, you have to opt-in for mutability and the compiler ensures that as long as a piece of data can be changed within a code segment (there is a mutable reference to the data), no other code path can read or modify the same data. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem with Immutability
&lt;/h3&gt;

&lt;p&gt;Making sure that the data you are referencing cannot change without your cooperation  generally makes your life easier. Unless this is EXACTLY what you want to achieve. Let's say you are writing a traffic monitoring tool. You might want to model your data like this (Elm syntax):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- In Elm, double dash marks a comment
type alias City =         --Curly braces declare a record type, a bit like an object
  { name: String
  , routes: List Route    --list of Route instances
  }

type alias Route =
  { from: City
  , to: City
  , trafficLevel: Float
  }

type alias World =
  { cities: List City
  , routes: List Route
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may expect that when you receive new traffic information, you simply work with &lt;code&gt;World.routes&lt;/code&gt; and the changes will be seen when accessing through &lt;code&gt;City.routes&lt;/code&gt;. But you would be mistaken. In Elm this will not even compile (fields in record types are fully expanded at compile time, and thus cannot have circular references). And if you use tagged unions to make the model compile, the &lt;code&gt;trafficLevel&lt;/code&gt; accessed via &lt;code&gt;World.routes&lt;/code&gt; may not be the same as one accessed via &lt;code&gt;City.routes&lt;/code&gt;, as those always behave as different instances.  &lt;/p&gt;

&lt;p&gt;A similar data model in Rust will compile but it will be difficult to actually instantiate the structure and you won't be able to ever modify the &lt;code&gt;trafficLevel&lt;/code&gt; of any &lt;code&gt;Route&lt;/code&gt; instance, because the compiler won't let you create a mutable reference to it (every &lt;code&gt;Route&lt;/code&gt; is referenced at least twice).&lt;/p&gt;

&lt;p&gt;This brings us to a less talked-about implication of immutability: &lt;strong&gt;immutable data structures are inherently tree-like&lt;/strong&gt;. In both Elm and Rust, it is a pain to work with graph-like structures and you have to give up some guarantees the languages give you.&lt;/p&gt;

&lt;p&gt;In Elm, the only way to represent a graph is by using indices to a dictionary (map) instead of direct references. For the above example a practical data model could look like:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type alias RouteId = Int    -- New types just for clarity
type alias CityId = Int 

type alias City =
  { id: CityId 
  , name: String
  , routes: List RouteId 
  }

type alias Route =
  { id: RouteId
  , from: City
  , to: City
  , trafficLevel: Float
  }

type alias World =
  { cities: Dict CityId City     --dictionary (map) with CityId as keys and City as values
  , routes: Dict RouteId Route
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice that nothing prevents us from having an invalid &lt;code&gt;RouteId&lt;/code&gt; stored in &lt;code&gt;City.routes&lt;/code&gt;. While Elm gives you good tools to work with such a model (e.g., it forces you to always handle the case where a given &lt;code&gt;RouteId&lt;/code&gt; is not present in &lt;code&gt;World.routes&lt;/code&gt;), and the advantages for every other use case make this an acceptable cost, it is still a bit annoying.&lt;/p&gt;

&lt;p&gt;Rust has a bit more options to work with graph-like data, but they all have downsides of their own (&lt;a href="http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/"&gt;using indices&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/34747464/implement-graph-like-datastructure-in-rust"&gt;StackOverflow discussion&lt;/a&gt;, &lt;a href="https://github.com/nrc/r4cppp/blob/master/graphs/README.md"&gt;graphs using ref counting or arena allocation&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart but Restrictive Compilers
&lt;/h2&gt;

&lt;p&gt;This is basically a generalization of the previous specific features. The compilers for Elm and Rust are powerful and they do a lot of stuff for you. They not only parse the code line-by-line, but they reason about your code in the context of the whole program. However, the most interesting thing about compilers for Rust and Elm is not what they let you do. It is what they DO NOT let you do (e.g., you cannot mix floats and ints without explicit conversion, you cannot get to the data stored in an tagged union without  handling all possible cases, you cannot modify certain data etc.). At the same time, the compilers are smart enough to make conforming to these restrictions less of a chore. If you think that programmers will produce better code when given fewer limitations, think of the time people complained that &lt;a href="http://web.archive.org/web/20090320002214/http://www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf"&gt;restricting the use of GOTO hinders productivity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another way to formulate this stance is that languages should not strive to make best practices easy as much as they should &lt;a href="http://www.haskellforall.com/2016/04/worst-practices-should-be-hard.html"&gt;make writing bad code hard&lt;/a&gt;. I think both languages achieve this to a good degree - writing &lt;em&gt;any&lt;/em&gt; code is a bit harder than in their less restrictive relatives, but there is much less incentive to take shortcuts.&lt;/p&gt;

&lt;p&gt;In practice, smart but restrictive compilers mean more time spent coding and less time spent debugging. Since debugging and reading messy code can be very time-consuming, this usually results in a net productivity gain. Personally, I love writing code, while debugging is often frustrating, so to me, this is a sweet deal.&lt;/p&gt;

&lt;p&gt;Needless to say, all those restrictions make hacking one-off dirty solutions in Rust or Elm slightly annoying. But what code is truly one-off?&lt;/p&gt;

&lt;h2&gt;
  
  
  Style matters
&lt;/h2&gt;

&lt;p&gt;The communities of both Elm and Rust make a big push for consistent presentation of source code. At the very least, this reduces the need for lengthy project-specific style guidelines at every team using the language. To be specific, Elm compiler enforces indentation for certain language constructs, &lt;a href="https://github.com/elm-lang/elm-compiler/issues/1370"&gt;does not allow Tabs for identation&lt;/a&gt;(!) and enforces that types begin with an upper-case letter while functions begin in lower-case. Further, there is &lt;a href="https://github.com/avh4/elm-format"&gt;elm-format&lt;/a&gt;, a community-endorsed source formatter. &lt;/p&gt;

&lt;p&gt;In a similar vein, Rust compiler gives warnings if you do not stick to official naming conventions and also provides a community-endorsed formatter &lt;a href="https://github.com/rust-lang-nursery/rustfmt"&gt;rustfmt&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  More About Elm
&lt;/h1&gt;

&lt;p&gt;Now is the time to talk about the languages individually, if you are still interested. We will take &lt;a href="http://elm-lang.org"&gt;Elm&lt;/a&gt; first. Elm is a simple, small language. The complete syntax can be &lt;a href="http://elm-lang.org/docs/syntax"&gt;documented on a single page&lt;/a&gt;. Elm aimes at people already using Javascript and strives for low barrier of entry. Elm is currently at version 0.18 and new releases regularly bring backwards-incompatible changes (although official conversion tools are available). An interesting thing is that over the last few versions more syntax elements were removed than added, testifying to the focus on language simplicity.&lt;/p&gt;

&lt;p&gt;Elm is purely functional. This means there are no variables in the classical sense, everything is a function. How does an application evolve over time if there are no variables? This is handled by &lt;a href="https://guide.elm-lang.org/architecture/"&gt;The Elm Architecture&lt;/a&gt; (TEA). On the most simplistic level, an Elm application consists primarily of an &lt;code&gt;update&lt;/code&gt; function and a &lt;code&gt;view&lt;/code&gt; function. The &lt;code&gt;update&lt;/code&gt; function takes a previous state of the application and input from the user/environment and returns a new state of the application. The &lt;code&gt;view&lt;/code&gt; function than takes the state of the application and returns a HTML representation. All changes to the application state thus happen outside of Elm code, within the native code in TEA. The architecture also provides the necessary  magic to correctly and efficiently update the DOM to match the latest &lt;code&gt;view&lt;/code&gt; result.&lt;/p&gt;

&lt;p&gt;TEA forces you to explicitly say what constitutes the state of your application and its inputs. This lets Elm to provide its killer feature: &lt;a href="http://elm-lang.org/blog/the-perfect-bug-report"&gt;the time-travel debugger&lt;/a&gt;. In essence, when the debugger is turned on, you can replay the whole history of the application and inspect the application state at any point in past. And due to the way the language is designed, it works 100% of the time.&lt;/p&gt;

&lt;p&gt;Another big plus of TEA is that you never have to worry about forgetting to hide an element when the user clicks a checkbox. If your &lt;code&gt;view&lt;/code&gt; function correctly displays the element based on the current application state, the element will also be automatically hidden once the application state changes again. &lt;/p&gt;

&lt;p&gt;Further sweet things about Elm is the effort to have &lt;a href="http://elm-lang.org/blog/compiler-errors-for-humans"&gt;nice and helpful error messages&lt;/a&gt;, with a dedicated GitHub repository for &lt;a href="https://github.com/elm-lang/error-message-catalog/issues"&gt;suggesting error message improvements&lt;/a&gt;. Also the &lt;a href="http://elm-lang.org/docs/records"&gt;record system&lt;/a&gt; which gives you a lot of freedom in using structured types (e.g., you do not have to declare them before use), but at the same time is statically checked for correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pain Points in Elm
&lt;/h2&gt;

&lt;p&gt;A big downside of TEA is that it assumes that all state of the application can be made explicit. This makes working with HTML elements that have a state of their own tricky in certain contexts (e.g., &lt;a href="https://groups.google.com/d/topic/elm-discuss/ALKjx3bsCgc/discussion"&gt;text area contents&lt;/a&gt;, &lt;a href="https://github.com/elm-lang/html/issues/55"&gt;caret position in text areas&lt;/a&gt;, Web Components). You need care to prevent TEA from messing with such components destructively. Further, TEA can be resource intensive, albeit &lt;a href="http://elm-lang.org/blog/blazing-fast-html-round-two"&gt;less than comparable JS frameworks&lt;/a&gt;. Last but not least, creating large apps in Elm involves writing a significant amount of boilerplate code. The Elm community is &lt;a href="https://groups.google.com/d/topic/elm-discuss/FHmv9hBdSA0/discussion"&gt;still discussing&lt;/a&gt; how to develop &lt;a href="https://groups.google.com/d/topic/elm-discuss/I1OBptGOU_A/discussion"&gt;large projects&lt;/a&gt; more &lt;a href="https://groups.google.com/forum/#!searchin/elm-discuss/large%7Csort:relevance/elm-discuss/2RTddO_4rLw/xOmzeg6wAgAJ"&gt;easily&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  More About Rust
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Whoa, that's a lot of new syntax!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rust book, &lt;a href="https://doc.rust-lang.org/beta/book/macros.html"&gt;section 4.34 on Macros&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;In comparison with Elm, Rust is quite the beast. There is a lot of syntax and a lot of things to learn. This is however not unexpected: if you want to write fast code, you really need a lot of control. Also, C and especially C++ also have loads of syntax, so Rust is definitely not at a big disadvantage here. Rust is currently at version 1.15 and has &lt;a href="https://blog.rust-lang.org/2014/10/30/Stability.html"&gt;forward compatibility guarantees&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While Rust is imperative, it took in a lot of useful functional programming concepts and boasts &lt;a href="https://blog.rust-lang.org/2015/05/11/traits.html"&gt;zero cost abstractions&lt;/a&gt; - i.e. that all the fancy syntactic tricks that let you develop code easily incur no actual performance penalty in comparison with a hand-tuned but dirty solution. &lt;/p&gt;

&lt;p&gt;Rust also has no OOP of the usual kind, instead it has &lt;a href="https://doc.rust-lang.org/book/traits.html"&gt;traits&lt;/a&gt; (a bit like interfaces) and deliberately avoids inheritance (you should compose instead).&lt;/p&gt;

&lt;p&gt;The weirdest and most interesting part of Rust is the &lt;a href="https://doc.rust-lang.org/book/ownership.html"&gt;borrow checker&lt;/a&gt;. While Rust does not have managed memory (garbage collection), it can still guarantee that you cannot access uninitialized memory, dereference a null pointer or otherwise corrupt your memory. This has big implications not only for reliability but also for security, as Rust automatically prevents whole classes of severe attacks as &lt;a href="https://en.wikipedia.org/wiki/Buffer_overflow"&gt;buffer overflow&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Heartbleed"&gt;Heartbleed&lt;/a&gt; (&lt;a href="https://tonyarcieri.com/would-rust-have-prevented-heartbleed-another-look"&gt;blog post&lt;/a&gt;). Rust also prevents most (but not all) memory leaks. The borrow checker is what enables a big portion of those guarantees by validating that your program accesses memory correctly at &lt;em&gt;compile time&lt;/em&gt;, i.e. without the runtime penalty of managed memory. The borrow checker ensures that a mutable reference to a piece of data cannot coexist with any other reference (and thus that you cannot free memory while holding a reference to it). For some intuition, mutable references in Rust behave a bit like &lt;code&gt;std::unique_ptr&lt;/code&gt;  in C++ (&lt;a href="http://en.cppreference.com/w/cpp/memory/unique_ptr"&gt;specs&lt;/a&gt;), but with the uniqueness enforced at compile-time. More detailed description could not fit here, so check &lt;a href="http://rustbyexample.com/scope/borrow.html"&gt;Rust by Example&lt;/a&gt; or just Google away :-).&lt;/p&gt;

&lt;h2&gt;
  
  
  Pain Points in Rust
&lt;/h2&gt;

&lt;p&gt;The borrow checker is both the biggest strength and the biggest weakness of Rust. Although the Rust community took a lot of effort to make most code just work, you inevitably end up &lt;a href="https://m-decoster.github.io//2017/01/16/fighting-borrowchk/"&gt;fighting&lt;/a&gt; the &lt;a href="https://ayende.com/blog/176801/the-struggle-with-rust"&gt;borrow checker&lt;/a&gt;. There are some promising &lt;a href="http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/"&gt;updates to the borrow checker&lt;/a&gt; in the pipeline that could make the life of Rust programmer easier, but it will not be cakewalk anytime soon - making the compiler understand your program is hard (both for the programmer and for the compiler).&lt;/p&gt;

&lt;p&gt;While Rust takes performance seriously and the compiler should &lt;em&gt;in theory&lt;/em&gt; be able to do a lot more optimizations than C/C++, Rust is not quite there yet. Benchmarks I've seen put it equal or slightly behind C/C++ on gcc (e.g. &lt;a href="http://benchmarksgame.alioth.debian.org/u64q/which-programs-are-fastest.html"&gt;Benchmarks game&lt;/a&gt;). From my memory gcc also used to produce slower code than MSVC or the Intel compiler which would be bad news for Rust. The Internet however suggests that recent gcc is on par with MSVC/Intel, but I was unable to find any good benchmark link.&lt;/p&gt;

&lt;p&gt;Development in Rust also still has some rough edges, &lt;a href="https://areweideyet.com/"&gt;IDE support is incomplete&lt;/a&gt; - setting up a decent debug environment maybe as much as a &lt;a href="https://sherryummen.in/2016/09/02/debugging-rust-on-windows-using-visual-studio-code/"&gt;14-step process&lt;/a&gt; and still the features are limited.&lt;/p&gt;

&lt;h1&gt;
  
  
  Concluding
&lt;/h1&gt;

&lt;p&gt;The same way functional programming has made its way from fringes to being included in mainstream languages, I believe the features that make both Elm and Rust interesting will show up in the mainstream.&lt;br&gt;
Some of the ideas can also be immediately transferred to the current languages (e.g. &lt;a href="https://facebook.github.io/immutable-js/"&gt;ImmutableJS&lt;/a&gt;). I think the take-home message of this post is that you should consider learning a new language. Preferably one that is very different from what you have been working with so far. No only it is fun, it will make you a better programmer in your language of choice.&lt;/p&gt;

&lt;p&gt;I'll be very happy if you provide your feedback on this post either here, on &lt;a href="https://twitter.com/martin_cerny_ai"&gt;my Twitter&lt;/a&gt; or &lt;a href="https://www.reddit.com/r/elm/comments/5srgwx/post_what_elm_and_rust_teach_us_about_the_future/"&gt;on Reddit&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>elm</category>
      <category>rust</category>
      <category>immutable</category>
      <category>typeinference</category>
    </item>
    <item>
      <title>Profiling Rust code on Windows using CodeXL</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Tue, 31 Jan 2017 11:08:26 +0000</pubDate>
      <link>https://forem.com/martinmodrak/profiling-rust-code-on-windows-using-codexl</link>
      <guid>https://forem.com/martinmodrak/profiling-rust-code-on-windows-using-codexl</guid>
      <description>&lt;p&gt;I like the &lt;a href="https://www.rust-lang.org" rel="noopener noreferrer"&gt;Rust language&lt;/a&gt;. However, developing with Rust on Windows currently has a lot of rough edges. One thing I was struggling with was a working solution for profiling Rust code on Windows. &lt;br&gt;
In the end, the best tool for the job I found was CodeXL (formerly known as AMD CodeXL). Here is a step-by-step tutorial on how it is done.&lt;br&gt;
The tutorial was tested on Windows 10 with Rust 1.14.0.&lt;/p&gt;

&lt;h1&gt;
  
  
  Note on Debugging and Targets
&lt;/h1&gt;

&lt;p&gt;To be able to debug the code I use the &lt;code&gt;x86_64-pc-windows-gnu&lt;/code&gt; target (as opposed to  &lt;code&gt;x86_64-pc-windows-msvc&lt;/code&gt; which is the default for Windows). &lt;br&gt;
However, the profiling experience is better with the MSVC target. So maybe the best approach is to switch between the targets based on your current needs using rustup:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; rustup default stable-x86_64-pc-windows-msvc
&amp;gt; rustup default stable-x86_64-pc-windows-gnu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;An aside on debugging on Windows. If you want to setup Rust debug environment on Windows, I recommend &lt;a href="https://sherryummen.in/2016/09/02/debugging-rust-on-windows-using-visual-studio-code/" rel="noopener noreferrer"&gt;Sherry Ummen's tutorial&lt;/a&gt; for&lt;br&gt;
setting up Rust + Visual Studio Code (requires the GNU target).&lt;br&gt;
I've heard good rumours about Rust support in Sublime and Atom, but have yet to test it myself.&lt;br&gt;
&lt;del&gt;AFAIK the debugging support in the &lt;a href="https://marketplace.visualstudio.com/items?itemName=vosen.VisualRust" rel="noopener noreferrer"&gt;Visual Studio 2015 extension&lt;/a&gt; is fairly limited and also requires the GNU target.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; In theory, you should be able to use standard debugger and profiler of Visual Studio (with the C++ toolset) to analyze code compiled with the MSVC target. I tried attaching Visual Studio debugger to a running Rust process (compiled with debug information) and it worked nicely! I was however unable to make the profiler work with the exact same program. I'll write another tutorial if I figure it out.&lt;/p&gt;

&lt;h1&gt;
  
  
  Profiling
&lt;/h1&gt;

&lt;p&gt;First thing we need to do is to compile the program optimized (otherwise profiling makes no sense), but with debugging information:&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;rustc -g -O -o rna.exe ..\src\main.rs&lt;br&gt;
 `&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you compile through Cargo, you should be able to set the necessary options by modifying the  &lt;code&gt;[profile.release]&lt;/code&gt; section of  &lt;code&gt;Cargo.toml&lt;/code&gt; file. See the &lt;a href="http://doc.crates.io/manifest.html" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Now open &lt;a href="https://github.com/GPUOpen-Tools/CodeXL" rel="noopener noreferrer"&gt;CodeXL&lt;/a&gt;. I have tested with version 1.9 and 2.2, but I believe other versions would work as well.&lt;/p&gt;

&lt;p&gt;First you switch to profile mode ( &lt;code&gt;Profile -&amp;gt; Switch to Profile Mode&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphf7jglhmd4xrtsesq86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphf7jglhmd4xrtsesq86.png" alt="Switch to profile mode" width="524" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My app was running pretty long, so I chose the easy path, started the app from command line and used  &lt;code&gt;Profile -&amp;gt; Attach to process&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoyhw14xclwndsxhafpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoyhw14xclwndsxhafpw.png" alt="Attach to process" width="468" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should be possible to have CodeXL start the app for you, but I didn't bother.&lt;/p&gt;

&lt;p&gt;Then you end the profiling by clicking the stop button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvm61f5q85d9ie7ms7ocw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvm61f5q85d9ie7ms7ocw.png" alt="Stop profiling" width="424" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you get the output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcbcq622gloy7dkj9dlh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcbcq622gloy7dkj9dlh.png" alt="Profile output" width="572" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can note, there are only two functions in the profiling output. That's not because my app has no functions, but because Rust inlined all the rest.&lt;/p&gt;

&lt;p&gt;This is the moment, when the GNU target bites you. If you compiled to GNU target, double-clicking on a function shows the actual time spent in individual processors instructions, but I found no simple way to match those instructions with the Rust code (and the inlined functions).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folea8214ss30fe0ggxp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folea8214ss30fe0ggxp3.png" alt="Function detail - GNU target" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, if you use the MSVC target, you see the actual source code! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8txqiauluuxra28i3rm0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8txqiauluuxra28i3rm0.png" alt="Function detail - MSVC target" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, even with MSVC, all samples attributed to an inlined function are associated with the line where the function is called, so you still see very little detail. &lt;br&gt;
To take the example above: is the  &lt;code&gt;next_cut()&lt;/code&gt; function really consuming so many samples or is the  &lt;code&gt;match&lt;/code&gt; statement responsible?&lt;/p&gt;

&lt;p&gt;So I did a little trick, that gives me more information, but may add noise to the timings. I forced the compiler to not inline anything:&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;rustc -g -O -C inline-threshold=0 -o rna.exe ..\src\main.rs&lt;br&gt;
 `&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which gives a more helpful result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u6f60vck6p809gub6ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u6f60vck6p809gub6ie.png" alt="Results - without inlining" width="538" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can now be quite confident that most of the time is spent in the actual body of  &lt;code&gt;main&lt;/code&gt; and  &lt;code&gt;find_next_cut&lt;/code&gt; and not in the inlined functions.&lt;/p&gt;

&lt;p&gt;I also tried the &lt;a href="https://github.com/VerySleepy/verysleepy" rel="noopener noreferrer"&gt;Very Sleepy profiler&lt;/a&gt;, which seemed to sort of work, &lt;br&gt;
but I could not get it to display any debug information (especially the function names).&lt;/p&gt;

&lt;p&gt;Hope this helps you!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>profiling</category>
      <category>tutorial</category>
      <category>windows</category>
    </item>
    <item>
      <title>Hi, I'm Martin ModrÃ¡k</title>
      <dc:creator>Martin Modrák</dc:creator>
      <pubDate>Mon, 30 Jan 2017 14:43:33 +0000</pubDate>
      <link>https://forem.com/martinmodrak/hi-im-martin-ern</link>
      <guid>https://forem.com/martinmodrak/hi-im-martin-ern</guid>
      <description>&lt;p&gt;I wrote my first program about 22 years ago and have been coding regularly since then.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/martinmodrak" rel="noopener noreferrer"&gt;martinmodrak&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Prague, Czech Republic (that's in Europe ;-) ).&lt;/p&gt;

&lt;p&gt;I work at the Czech Academy of Sciences as researcher/programmer.&lt;/p&gt;

&lt;p&gt;I have biggest experience in Java, but I have switched projects and languages frequently. I thus also feel comfortable in C#, Python, C++ and recently Elm.&lt;/p&gt;

&lt;p&gt;I am currently learning more about Elm, Rust and OpenCL.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
