<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Turtletopia: a blog about programming in R</title>
    <link>https://turtletopia.github.io</link>
    <description>Recent content on Turtletopia: a blog about programming in R</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 31 Aug 2022 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://turtletopia.github.io/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Shiny Reactivity Tricks, pt. II: Reactives Factories</title><enclosure url="factory.png" type="image/jpg"></enclosure>
      
      <link>https://turtletopia.github.io/2022/08/31/shiny-reactivity-tricks-pt-ii-reactives-factories/</link>
      <pubDate>Wed, 31 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/08/31/shiny-reactivity-tricks-pt-ii-reactives-factories/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#preface&#34; id=&#34;toc-preface&#34;&gt;Preface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#basic-example&#34; id=&#34;toc-basic-example&#34;&gt;Basic example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-1-wrap-a-function-with-a-reactive.&#34; id=&#34;toc-solution-1-wrap-a-function-with-a-reactive.&#34;&gt;Solution 1: wrap a function with a reactive.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-2a-and-2b-extract-input.&#34; id=&#34;toc-solution-2a-and-2b-extract-input.&#34;&gt;Solution 2a and 2b: extract input.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-3-wrap-a-reactive-with-a-function-factory.&#34; id=&#34;toc-solution-3-wrap-a-reactive-with-a-function-factory.&#34;&gt;Solution 3: wrap a reactive with a function (factory).&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#discussion-summary&#34; id=&#34;toc-discussion-summary&#34;&gt;Discussion &amp;amp; summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div id=&#34;preface&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Preface&lt;/h1&gt;
&lt;p&gt;There was no post last week because the holiday season/master’s thesis finishing season/parental pet care season is in full swing, and I’ve been completely crushed. This week isn’t easy either, but I didn’t want to leave you empty-handed when there’s so much to talk about!&lt;/p&gt;
&lt;p&gt;This time I wanted to present you with another installment in the shiny tricks series. I’m going to show something that isn’t quite as ‘tricky’ but can still be non-obvious to those who don’t use reactivity and environments proficiently. I will tell you about factories of reactives. And the tale starts with an example.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Basic example&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Remark:&lt;/strong&gt; As I often use the &lt;code&gt;shiny::reactive()&lt;/code&gt; function in this article, it will probably not have escaped you that I always wrap the first argument of this function in curly brackets. By doing so, I make it clear that the function’s argument is &lt;em&gt;an expression&lt;/em&gt;, not its &lt;em&gt;value&lt;/em&gt;. Most of the time, this is not necessary, but it is a habit of mine and helps me keep the code readable.&lt;/p&gt;
&lt;p&gt;Suppose we have an application that accepts several numeric inputs that perform very complex transformations, then plots and outputs the result. Let’s start with an example with two inputs.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(shiny)

ui &amp;lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput(&amp;quot;a&amp;quot;, &amp;quot;input a&amp;quot;, 1, 0, 100, 1),
      numericInput(&amp;quot;b&amp;quot;, &amp;quot;input b&amp;quot;, 1, 0, 100, 1)
    ),
    mainPanel(
      textOutput(&amp;quot;text_a_b&amp;quot;),
      plotOutput(&amp;quot;plot_a_b&amp;quot;)
    )
  )
)

server &amp;lt;- function(input, output, session) {
  temp_val &amp;lt;- reactive({
    c(
      input[[&amp;quot;a&amp;quot;]] + input[[&amp;quot;b&amp;quot;]],
      input[[&amp;quot;a&amp;quot;]]^3 * input[[&amp;quot;b&amp;quot;]],
      27 - (input[[&amp;quot;b&amp;quot;]] + input[[&amp;quot;a&amp;quot;]])
    )
  })

  output[[&amp;quot;text_a_b&amp;quot;]] &amp;lt;- renderText(
    paste(temp_val(), collapse = &amp;quot; -- &amp;quot;)
  )
  output[[&amp;quot;plot_a_b&amp;quot;]] &amp;lt;- renderPlot(
    plot(temp_val(), temp_val())
  )
}

shinyApp(ui, server)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/reactives-factory-example.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Basic example app.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This application takes two inputs and performs an incredibly complex calculation that, in effect, returns a three-element vector. This vector, an intermediate value, is later used for the two outputs.&lt;/p&gt;
&lt;p&gt;Of course, again, the calculations themselves, the inputs and outputs, are not relevant or even meaningful here. It’s just my usual problem finding simple examples to demonstrate not-so-simple concepts. The only important thing is a reactive intermediate value calculated from inputs.&lt;/p&gt;
&lt;p&gt;So far, nothing complicated. So let’s add a little spice.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ui &amp;lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput(&amp;quot;a&amp;quot;, &amp;quot;input a&amp;quot;, 1, 0, 100, 1),
      numericInput(&amp;quot;b&amp;quot;, &amp;quot;input b&amp;quot;, 1, 0, 100, 1),
      numericInput(&amp;quot;c&amp;quot;, &amp;quot;input c&amp;quot;, 1, 0, 100, 1),
      numericInput(&amp;quot;d&amp;quot;, &amp;quot;input d&amp;quot;, 1, 0, 100, 1),
      numericInput(&amp;quot;e&amp;quot;, &amp;quot;input e&amp;quot;, 1, 0, 100, 1)
    ),
    mainPanel(
      textOutput(&amp;quot;text_a_b&amp;quot;),
      plotOutput(&amp;quot;plot_a_b&amp;quot;),
      plotOutput(&amp;quot;plot_b_d&amp;quot;),
      tableOutput(&amp;quot;table_c_d&amp;quot;),
      textOutput(&amp;quot;table_a_e&amp;quot;)
    )
  )
)

server &amp;lt;- function(input, output, session) {
  temp_val_1 &amp;lt;- reactive({
    c(
      input[[&amp;quot;a&amp;quot;]] + input[[&amp;quot;b&amp;quot;]],
      input[[&amp;quot;a&amp;quot;]]^3 * input[[&amp;quot;b&amp;quot;]],
      27 - (input[[&amp;quot;b&amp;quot;]] + input[[&amp;quot;a&amp;quot;]])
    )
  })

  temp_val_2 &amp;lt;- reactive({
    c(
      input[[&amp;quot;b&amp;quot;]] + input[[&amp;quot;d&amp;quot;]],
      input[[&amp;quot;b&amp;quot;]]^2 * input[[&amp;quot;d&amp;quot;]],
      8 - (input[[&amp;quot;d&amp;quot;]] + input[[&amp;quot;b&amp;quot;]])
    )
  })

  temp_val_3 &amp;lt;- reactive({
    c(
      input[[&amp;quot;c&amp;quot;]] + input[[&amp;quot;d&amp;quot;]],
      input[[&amp;quot;c&amp;quot;]] * input[[&amp;quot;d&amp;quot;]],
      1 - (input[[&amp;quot;d&amp;quot;]] + input[[&amp;quot;c&amp;quot;]])
    )
  })

  temp_val_4 &amp;lt;- reactive({
    c(
      input[[&amp;quot;a&amp;quot;]] + input[[&amp;quot;e&amp;quot;]],
      input[[&amp;quot;a&amp;quot;]]^4 * input[[&amp;quot;e&amp;quot;]],
      64 - (input[[&amp;quot;e&amp;quot;]] + input[[&amp;quot;a&amp;quot;]])
    )
  })

  output[[&amp;quot;text_a_b&amp;quot;]] &amp;lt;- renderText(
    paste(temp_val_1(), collapse = &amp;quot; -- &amp;quot;)
  )
  output[[&amp;quot;plot_a_b&amp;quot;]] &amp;lt;- renderPlot(
    plot(temp_val_1(), temp_val_1())
  )
  output[[&amp;quot;plot_b_d&amp;quot;]] &amp;lt;- renderPlot(
    plot(c(1, 1, 1), temp_val_2())
  )
  output[[&amp;quot;table_c_d&amp;quot;]] &amp;lt;- renderTable(
    data.frame(x = temp_val_3(), e = exp(temp_val_3()))
  )
  output[[&amp;quot;table_a_e&amp;quot;]] &amp;lt;- renderText(temp_val_4())
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I modified the UI and the server to do more things. Everything is centered around the very complex transformation as before, but we have more inputs, more outputs, and more temporary values. And above all: more iterations. As you may have already realized, I’m a prominent opponent of repetition in code: if there’s copy-paste somewhere, it can probably be done better. And that’s what we’re going to try to address. This code has two primary repeating rhythms: inputs and the calculation of temporary values. We can fix the first repetition very quickly, and I’ve already done similar things in &lt;a href=&#34;https://turtletopia.github.io/2022/07/09/creating-observers-in-loop-shiny-reactivity-tricks-episode-one/&#34;&gt;the last part of the article series&lt;/a&gt;, so I won’t go into it this time. Let’s deal with the more exciting thing, which is the server-side repetitions.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-1-wrap-a-function-with-a-reactive.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 1: wrap a function with a reactive.&lt;/h1&gt;
&lt;p&gt;The thing that jumps to mind almost immediately is the creation of a function that generates these temporary values.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
magic_func &amp;lt;- function(name_1, name_2, param) c(
  name_1 + name_2,
  name_1^param * name_2,
  param^3 - (name_2 + name_1)
)

server &amp;lt;- function(input, output, session) {
  temp_val_1 &amp;lt;- reactive({ magic_func(input[[&amp;quot;a&amp;quot;]], input[[&amp;quot;b&amp;quot;]], 3) })
  temp_val_2 &amp;lt;- reactive({ magic_func(input[[&amp;quot;b&amp;quot;]], input[[&amp;quot;d&amp;quot;]], 2) })
  temp_val_3 &amp;lt;- reactive({ magic_func(input[[&amp;quot;c&amp;quot;]], input[[&amp;quot;d&amp;quot;]], 1) })
  temp_val_4 &amp;lt;- reactive({ magic_func(input[[&amp;quot;a&amp;quot;]], input[[&amp;quot;e&amp;quot;]], 4) })

  # here, put the other part of the server code...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This already looks much, much better! It’s more readable and less error-proof, so the advantages alone. And that’s basically where we could leave it. But if it satisfied us, we wouldn’t read any further.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-2a-and-2b-extract-input.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 2a and 2b: extract input.&lt;/h1&gt;
&lt;p&gt;Another thing that we can improve in this solution is to refer to the &lt;code&gt;input&lt;/code&gt; object every time there are multiple arguments to the &lt;code&gt;magic_func()&lt;/code&gt; function. So maybe we can move this reference inside the function?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
magic_func &amp;lt;- function(name_1, name_2, param) c(
  input[[name_1]] + input[[name_2]],
  input[[name_1]]^param * input[[name_2]],
  param^3 - (input[[name_2]] + input[[name_1]])
)

server &amp;lt;- function(input, output, session) {
  temp_val_1 &amp;lt;- reactive({ magic_func(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, 3) })
  temp_val_2 &amp;lt;- reactive({ magic_func(&amp;quot;b&amp;quot;, &amp;quot;d&amp;quot;, 2) })
  temp_val_3 &amp;lt;- reactive({ magic_func(&amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;, 1) })
  temp_val_4 &amp;lt;- reactive({ magic_func(&amp;quot;a&amp;quot;, &amp;quot;e&amp;quot;, 4) })
  
  # here, put the other part of the server code...
}&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/reactives-factory-error.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Output error message.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Unfortunately, we will find that this is not enough. The &lt;code&gt;input&lt;/code&gt; object is for the interior of the function unknown. That may seem unnatural if you understand the basics of how scopes work in R – if the object is not found in the current environment, the parent environment is checked (I talked about this in &lt;a href=&#34;https://turtletopia.github.io/2022/07/09/creating-observers-in-loop-shiny-reactivity-tricks-episode-one/&#34;&gt;the last part of the series&lt;/a&gt;, I refer you to it again). Here, however, this situation is not so evident because the server environment is not in the search path of the environment in which the function is defined.&lt;/p&gt;
&lt;p&gt;That can be resolved in two ways: either move the function definition inside the server or pass an &lt;code&gt;input&lt;/code&gt; object as an additional parameter to the function. I leave the proof to the reader.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-3-wrap-a-reactive-with-a-function-factory.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 3: wrap a reactive with a function (factory).&lt;/h1&gt;
&lt;p&gt;However, we could go even further and reduce code redundancy. And this is where we want to create a reactive factory.&lt;/p&gt;
&lt;p&gt;What is a factory of reactives? It is simply a function that creates a reactive. Every shiny user should be familiar with the primary function used to create and register reactives – namely, &lt;code&gt;shiny::reactive()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But this is the most general factory that exists – you pass it any expression, turning it into a reactive expression. We would like to have something more concrete, i.e. instead of writing &lt;code&gt;reactive({ fun(parameters) })&lt;/code&gt; writing &lt;code&gt;reactive_fun(parameters)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we want to replace&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;reactive({ magic_func(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, 3) })&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r_magic_func(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, 3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice the &lt;code&gt;r_&lt;/code&gt; I added to the function name. Suggesting that this function returns a reactive is a good idea.&lt;/p&gt;
&lt;p&gt;So, let’s try to make such a function!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r_magic_func &amp;lt;- function(name_1, name_2, param) reactive({
  c(
    input[[name_1]] + input[[name_2]],
    input[[name_1]]^param * input[[name_2]],
    param^3 - (input[[name_2]] + input[[name_1]])
  )
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Does it work? Yes… at least: almost. It will not work unless we consider our previous solution’s experiences: it needs to be either defined in the server function or take input as a separate parameter.&lt;/p&gt;
&lt;p&gt;But what if we do not want to do either of those? We are lazy and do not want to type all the parameters that will look the same either way. Those “inputs” typed every time are annoying, but if, in addition, we have some other reactive values that we would have to pass on each time, this would be very annoying. On the other hand, defining functions within a server works for small apps but is terrible if you have an extensive, packaged application that wants to keep its code tidy and test its functions with unit tests. So how do we get around these obstacles?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reactive&lt;/code&gt; has additional parameters that are worth looking at. Of particular interest to us is the &lt;code&gt;env&lt;/code&gt; parameter. It indicates the environment in which the expression passed as the first parameter should be evaluated. That is usually set as the environment calling the &lt;code&gt;reactive&lt;/code&gt; function. So this is the reason why our original factory is not able to see the &lt;code&gt;input&lt;/code&gt; object – it is not in the environment calling the &lt;code&gt;reactive&lt;/code&gt;. So what happens if we replace this environment with the environment which calls our factory function?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r_magic_func &amp;lt;- function(name_1, name_2, param) reactive({
  c(
    input[[name_1]] + input[[name_2]],
    input[[name_1]]^param * input[[name_2]],
    param^3 - (input[[name_2]] + input[[name_1]])
  )
}, env = rlang::caller_env())&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/reactives-factory-error-2.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;We got a different error! That’s progress!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Why are we getting this error this time? Since we replaced the evaluation environment with the caller environment, it can see all objects available in the server environment. Still, it cannot see the objects available inside the &lt;code&gt;r_magic_func&lt;/code&gt; – namely, name_1 (pun intended) and other parameters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Our favorite package comes to our rescue: rlang!&lt;/strong&gt; We can use a similar idea with an injection of values just as in the &lt;a href=&#34;https://turtletopia.github.io/2022/07/09/creating-observers-in-loop-shiny-reactivity-tricks-episode-one/&#34;&gt;previous tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r_magic_func &amp;lt;- function(name_1, name_2, param) rlang::inject({
  reactive({
    c(
      input[[!!name_1]] + input[[!!name_2]],
      input[[!!name_1]]^(!!param) * input[[!!name_2]],
      (!!param)^3 - (input[[!!name_2]] + input[[!!name_1]])
    )
  }, env = rlang::caller_env())
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it fulfills all of our objectives! One more thing to do: if we want to take care of the &lt;code&gt;r_magic_func&lt;/code&gt;, we should ensure that this factory can also be called within other functions. So, instead of fixing the &lt;code&gt;env&lt;/code&gt; parameter of &lt;code&gt;reactive&lt;/code&gt; as the &lt;code&gt;rlang::caller_env()&lt;/code&gt;, we should make it a default parameter of &lt;code&gt;r_magic_func&lt;/code&gt;, similarly to &lt;code&gt;reactive&lt;/code&gt; itself does it.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;discussion-summary&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Discussion &amp;amp; summary&lt;/h1&gt;
&lt;p&gt;My example will probably seem too artificial and contrived to some of you. I am not writing this for the sake of the brilliance of the example but rather to teach the concept behind it. Probably many of you will find a suitable application for this method. Some may agitate that hiding the reactive behind a function is superfluous, but, in my opinion, it is just another step towards code readability. This kind of factory can be further generalized and improved, which I will discuss next time.&lt;/p&gt;
&lt;p&gt;One more thing: modules. I still deliberately avoid using modules. What I am doing here could also be done using modules, although I think it is much less intuitive than in the last part of the series. I will also write about modules another time (ah, too many of these topics!).&lt;/p&gt;
&lt;p&gt;I have shown you how to use tools to change the evaluation environment to control code execution and, as a result, reduce unnecessary repetitions. This is only the second step on the long road to becoming a master at using the language to its full potential. If you have any questions or comments, contact us &lt;a href=&#34;https://twitter.com/Rturtletopia&#34;&gt;on Twitter&lt;/a&gt; or make an issue &lt;a href=&#34;https://github.com/turtletopia/turtletopia.github.io/issues&#34;&gt;on Github&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Show Pride on Your Plots</title><enclosure url="palettes.png" type="image/jpg"></enclosure>
      
      <link>https://turtletopia.github.io/2022/08/12/show-pride-on-your-plots/</link>
      <pubDate>Fri, 12 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/08/12/show-pride-on-your-plots/</guid>
      <description>


&lt;p&gt;This will be a short post, since I’m busy playing blues this week. At least the topic’s short!&lt;/p&gt;
&lt;p&gt;It all began with a post by RainbowR on Twitter:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Alright, RainbowRs, show us your blogs/websites! Quarto/distill/blogdown/whatever - we love to see it! &lt;a href=&#34;https://t.co/SivyCaY0yi&#34;&gt;https://t.co/SivyCaY0yi&lt;/a&gt;&lt;/p&gt;&amp;mdash; RainbowR (@R_LGBTQ) &lt;a href=&#34;https://twitter.com/R_LGBTQ/status/1555450735390871552?ref_src=twsrc%5Etfw&#34;&gt;August 5, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;As a very curious person, I had to check their GitHub account. And I found a repository curiously named &lt;a href=&#34;https://github.com/r-lgbtq/pridepalettes&#34;&gt;pridepalettes&lt;/a&gt;. I was a little disappointed to find out it’s just a single script with little reusability. I hoped for a package!&lt;/p&gt;
&lt;p&gt;A quick research showed me a few more repos with pride colors, but none I could download from CRAN. In fact, only one was a package at all!&lt;/p&gt;
&lt;p&gt;So I took matters into my own hands and created &lt;a href=&#34;https://github.com/turtletopia/gglgbtq&#34;&gt;gglgbtq&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It would be easy to just scrape the colors of multiple flags, slap a &lt;code&gt;palette_lgbtq()&lt;/code&gt; function on top of ’em, and call it a day. But it would be barely usable. Have you ever used white for a group with default ggplot2 settings? It’d be barely visible.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# I swear it&amp;#39;s the last time I&amp;#39;d use iris dataset
library(ggplot2)
library(gglgbtq)
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) +
  geom_point(size = 2) +
  scale_color_manual(values = palette_lgbtq(&amp;quot;genderqueer&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://turtletopia.github.io/2022/08/12/show-pride-on-your-plots/index_files/figure-html/genderqueer_no_theme-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This is why I included &lt;code&gt;theme_lgbtq()&lt;/code&gt;. Each palette has its own custom theme for increased readability (although many themes are reused across multiple palettes). Check out the difference!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Is it considered &amp;quot;another time&amp;quot; or just &amp;quot;the last use part II&amp;quot;?
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) +
  geom_point(size = 2) +
  scale_color_manual(values = palette_lgbtq(&amp;quot;genderqueer&amp;quot;)) +
  theme_lgbtq(&amp;quot;genderqueer&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://turtletopia.github.io/2022/08/12/show-pride-on-your-plots/index_files/figure-html/genderqueer_w_theme-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The difference isn’t much, but I found this gray to be the perfect balance for most palettes that include white (which is like 85% or so of all LGBT+ flags). But there are palettes without white, like this one:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# I spent like 10 minutes sifting through the base datasets
# but - behold! - a non-iris dataset at last
ggplot(warpbreaks, aes(x = wool, y = breaks, fill = tension)) +
  geom_bar(stat = &amp;quot;identity&amp;quot;, position = &amp;quot;dodge&amp;quot;) +
  scale_fill_manual(values = palette_lgbtq(&amp;quot;pansexual&amp;quot;)) +
  theme_lgbtq(&amp;quot;pansexual&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://turtletopia.github.io/2022/08/12/show-pride-on-your-plots/index_files/figure-html/pansexual_w_theme-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For now I included 16 palettes, but expect more (and if you want a specific flag to be included in the next release, write an issue on GitHub, strike a message on Twitter, or send a pigeon with a letter):&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;palettes.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;The Pride Palettes (edition gglgbtq 0.1.0)&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Like what you see? You can get it from CRAN or &lt;a href=&#34;https://github.com/turtletopia/gglgbtq&#34;&gt;GitHub&lt;/a&gt;, whichever suits you best:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;install.packages(&amp;quot;gglgbtq&amp;quot;)
remotes::install_github(&amp;quot;turtletopia/gglgbtq&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Show us your pride plots on Twitter, we’d love to see them!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sonnet to infix function</title><enclosure url="https://turtletopia.github.io/images/logo.png" type="image/jpg"></enclosure>
      <link>https://turtletopia.github.io/2022/08/10/sonnet-to-infix-function/</link>
      <pubDate>Wed, 10 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/08/10/sonnet-to-infix-function/</guid>
      <description>


&lt;div id=&#34;some-poetry-for-the-programmers&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Some poetry for the programmers&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Blest be the day, and blest be the month and year,&lt;/p&gt;
&lt;p&gt;Season and hour and very moment blest,&lt;/p&gt;
&lt;p&gt;The lovely IDE where first possessed&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;By two percent signs I found me prisoner; (…)&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Francesco Petrarch, Sonnet 61. Translated by Joseph Auslander. Possibly with some spicing it up by me&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div id=&#34;subject-and-addressee-of-the-poem&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Subject and addressee of the poem&lt;/h1&gt;
&lt;p&gt;Custom infix functions are one of my favorite features in R. This article is my love letter to them. But first, a quick recap.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with the terminology, &lt;em&gt;infix function&lt;/em&gt; is a function &lt;code&gt;fun&lt;/code&gt; which is called using &lt;code&gt;infix notation&lt;/code&gt;, e.g., &lt;code&gt;x fun y&lt;/code&gt; instead of &lt;code&gt;fun(x, y)&lt;/code&gt;. Those functions are also called &lt;em&gt;infix operators&lt;/em&gt; by base R, and I will use those terms and name &lt;em&gt;infixes&lt;/em&gt; interchangeably. There are a lot of infix operators in base R used very frequently, i.e., arithmetic or logical operators. We use them so often that we usually forget that they are functions. And that we can &lt;strong&gt;call them just like regular functions&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;23 + 19&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 42&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`+`(23, 19)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 42&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you may have noticed, when calling such a function in a non-infix-manner, we need to use backticks around the operator to avoid calling it regularly.&lt;/p&gt;
&lt;p&gt;To prove that they share a lot of typical behavior with functions, I am going to demonstrate to you how to &lt;strong&gt;redefine them just like regular functions&lt;/strong&gt;. We can, for example, make the &lt;code&gt;+&lt;/code&gt; operator work like a multiplication.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`+` &amp;lt;- function(lhs, rhs) lhs * rhs
23 + 19&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 437&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let it ring out loud: &lt;strong&gt;you should not do that at all&lt;/strong&gt;. Overriding the default behavior of functions may be dangerous, as it interferes with other chunks of code using the operator. I showed this trick only for demonstration purposes.&lt;/p&gt;
&lt;p&gt;(Side note: you might be aware that some packages change the default behavior of operators, e.g., &lt;code&gt;ggplot2&lt;/code&gt; has its own &lt;code&gt;+&lt;/code&gt; for joining plot elements. However, this is a slightly different situation. They do not create a whole new function but only add a &lt;em&gt;method&lt;/em&gt; for &lt;em&gt;generic function&lt;/em&gt;. They do not &lt;em&gt;override&lt;/em&gt; the behavior, but more like &lt;em&gt;overload&lt;/em&gt; it.)&lt;/p&gt;
&lt;p&gt;Additional remark to make: in this assignment call, backticks are also necessary. An alternative is using quotes, but it is inadvisable, and its presence in the language is entirely due to legacy reasons. You can read more about it in &lt;a href=&#34;https://adv-r.hadley.nz/names-values.html#non-syntactic&#34;&gt;Hadley’s book&lt;/a&gt;. In &lt;a href=&#34;https://adv-r.hadley.nz/functions.html?q=infix#infix-functions&#34;&gt;another chapter&lt;/a&gt;, you can find more about infix functions.&lt;/p&gt;
&lt;p&gt;Once again: &lt;strong&gt;do not override built-in infix functions&lt;/strong&gt;. BUT. &lt;strong&gt;Create custom infix functions!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;R allows for creating your operators using double &lt;strong&gt;percent signs&lt;/strong&gt;. A few shipped with the base R packages, including inclusion operator &lt;code&gt;%in%&lt;/code&gt; (pun intended) or matrix multiplication operator &lt;code&gt;%*%&lt;/code&gt;. But You can create more. And we will explore it in the next section.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;enumeration-is-an-important-stylistic-device&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Enumeration is an important stylistic device&lt;/h1&gt;
&lt;div id=&#34;piping-operators&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Piping operators&lt;/h2&gt;
&lt;p&gt;The most widely known example is the piping operator: &lt;code&gt;%&amp;gt;%&lt;/code&gt;. I assume that you are familiar with it. If not, &lt;a href=&#34;https://dplyr.tidyverse.org/&#34;&gt;you better get to know the dplyr package&lt;/a&gt;. The pipe comes from &lt;a href=&#34;https://magrittr.tidyverse.org/&#34;&gt;magrittr&lt;/a&gt; package, but dplyr shows its natural strength and the most significant advantage of using custom operators: &lt;strong&gt;custom infixes make code more readable&lt;/strong&gt;. When we apply operations one by one, it makes more sense to write those operations in order of application, not inverse order, as we do without infix operators. The operator’s shape is also essential, as it suggests the direction of the data flow. For me, it is more natural to read and understand&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x %&amp;gt;% 
  fun_1 %&amp;gt;% 
  fun_2 %&amp;gt;% 
  fun_3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rather than&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;fun_3(fun_2(fun_1(x)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It became so popular that R 4.1.0 included its pipe, &lt;code&gt;|&amp;gt;&lt;/code&gt;. However, I will not dwell more on that because others have already said a lot about pipes. I only want to mention, what is often forgotten by newcomers, that magrittr offer more than one type of pipe. Go check them out if you don’t know them!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;null-default-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;NULL-default operator&lt;/h2&gt;
&lt;p&gt;Another tremendous and straightforward function is &lt;code&gt;%||%&lt;/code&gt;. It is exported by the &lt;em&gt;rlang&lt;/em&gt; package (it’s the turtleblog after all”, so rlang mention is obligatory), but other packages borrow this idea to avoid dependency. The code is straightforward and clearly explains what the function is intended to do.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`%||%` &amp;lt;- function(lhs, rhs) if (is.null(lhs)) rhs else lhs

34 %||% 8&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 34&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;NULL %||% 10&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This one comes in handy when you have optional &lt;code&gt;NULL&lt;/code&gt;s returned by a function or possibly &lt;code&gt;NULL&lt;/code&gt; parameters of the function or named function arguments. In the code, it looks way more straightforward than the expansion of the function definition itself. I usually do not export such a helper function to the end user. But it is worth repeating that &lt;strong&gt;readability of your code for yourself should be as important as readability for others&lt;/strong&gt;. If such infixes help you, then you should use them.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;null-propagating-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;NULL-propagating operator&lt;/h2&gt;
&lt;p&gt;Let’s stay with &lt;code&gt;NULL&lt;/code&gt;-related functions for a little longer. Now it is time for my creation. When I build packages or shiny apps, it happens quite often that I need to apply some function to some object, but if it is &lt;code&gt;NULL&lt;/code&gt;, I need to return &lt;code&gt;NULL&lt;/code&gt;. For those situations, I created the &lt;code&gt;%?&amp;gt;%&lt;/code&gt; operator:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`%?&amp;gt;%` &amp;lt;- function(lhs, rhs) if (is.null(lhs)) NULL else rhs(lhs)

7 %?&amp;gt;% exp&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 1096.633&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;NULL %?&amp;gt;% exp&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## NULL&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This one is some modification of a standard pipe but serves a specific purpose. It simplified my code significantly, and I love it for its &lt;strong&gt;conciseness&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;motif-inclusion-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Motif inclusion operator&lt;/h2&gt;
&lt;p&gt;Now, an example from one of our packages, &lt;em&gt;tidysq&lt;/em&gt;. It is a package for the tidy processing of biological sequences. Here we implemented the &lt;code&gt;%has%&lt;/code&gt; operator that checks for the presence of specific motifs in sequences.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidysq)

sq(c(&amp;quot;AAAA&amp;quot;, &amp;quot;AGCA&amp;quot;, &amp;quot;CGCG&amp;quot;, &amp;quot;TTCG&amp;quot;)) %has% &amp;quot;GC&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] FALSE  TRUE  TRUE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Laura and I found it very in line with the tidyverse philosophy of code being readable and understandable by others. It can be especially seen in &lt;code&gt;dplyr&lt;/code&gt; processing pipes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)

tibble(
  id = 1:4,
  sequence = c(&amp;quot;LVGWEK&amp;quot;, &amp;quot;KLLCVN&amp;quot;, &amp;quot;ER&amp;quot;, &amp;quot;LLLY&amp;quot;)
 ) %&amp;gt;%
  mutate(sequence = sq(sequence)) %&amp;gt;%
  filter(sequence %has% &amp;quot;LL&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 2 × 2
##      id sequence  
##   &amp;lt;int&amp;gt; &amp;lt;ami_bsc&amp;gt; 
## 1     2 KLLCVN &amp;lt;6&amp;gt;
## 2     4 LLLY   &amp;lt;4&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;ternary-if-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ternary if operator&lt;/h2&gt;
&lt;p&gt;Finally, one fancy trick! Have you programmed in any language that contains ternary if operator? E.g., in C++, it looks like this:&lt;/p&gt;
&lt;pre class=&#34;cpp&#34;&gt;&lt;code&gt;(1 &amp;gt; 0) ? &amp;#39;A&amp;#39; : &amp;#39;B&amp;#39;

// would return &amp;#39;A&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the expression on LHS of &lt;code&gt;?&lt;/code&gt; is TRUE, a value between &lt;code&gt;?&lt;/code&gt; and &lt;code&gt;:&lt;/code&gt; is returned. Otherwise, the value after &lt;code&gt;:&lt;/code&gt; is returned. Why use it over regular if-else? It is an &lt;em&gt;expression&lt;/em&gt;, while standard &lt;code&gt;if&lt;/code&gt; in C and C++ is not an expression. Thus, the user can assign the result of this expression to any variable.&lt;/p&gt;
&lt;p&gt;Do you miss it in R? Probably not. In R, &lt;code&gt;if&lt;/code&gt; is an expression, so we have:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;if (1 &amp;gt; 0) &amp;quot;A&amp;quot; else &amp;quot;B&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;A&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if we &lt;em&gt;really&lt;/em&gt; wanted to have something in R more like in C++? Here you go!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`%?%` &amp;lt;- function(lhs, rhs) {
  values &amp;lt;- rlang::enexpr(rhs)
  if (values[[1]] != as.symbol(&amp;quot;:&amp;quot;))
    stop(&amp;quot;RHS for `%?%` operator has to be in the form of &amp;#39;*:*&amp;#39; where &amp;#39;*&amp;#39; are any expressions&amp;quot;)
  if (lhs) rlang::eval_bare(values[[2]]) else rlang::eval_bare(values[[3]])
}

(1 &amp;gt; 0) %?% &amp;quot;A&amp;quot; : &amp;quot;B&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;A&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I did it only because &lt;em&gt;I can&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As you can see, I also abused the &lt;code&gt;:&lt;/code&gt; operator; not overrode: &lt;em&gt;abused&lt;/em&gt;. Inside the function, the RHS argument is in the form &lt;code&gt;expr:expr&lt;/code&gt;. Normally that would result in range. But here I used the &lt;strong&gt;non-standard evaluation&lt;/strong&gt;, using &lt;code&gt;rlang::enexpr()&lt;/code&gt; and &lt;code&gt;ralng::eval_bare()&lt;/code&gt; to actually stop R from doing what it usually does. I will probably go into detail about it some other time; right now, enjoy the fanciness.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;remark-about-precedence&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Remark about precedence&lt;/h2&gt;
&lt;p&gt;One thing to remember: &lt;strong&gt;operators have specific precedence&lt;/strong&gt;. Those that have been programming for longer know that well from an autopsy. Those that have just started programming &lt;em&gt;will&lt;/em&gt; get to know that. Custom infix functions obey those rules as well, and you sometimes may get surprised. You can check that the operators I provided may sometimes be misleading and require parentheses to work correctly. It is worth checking out &lt;a href=&#34;https://rdrr.io/r/base/Syntax.html&#34;&gt;R operator precedence manual page&lt;/a&gt; when in doubt.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;the-strange-sibling-of-my-love&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The strange sibling of my love&lt;/h1&gt;
&lt;p&gt;As a side note, I wanted to mention one operator I was unaware of before writing the article. Or: I was not fully aware of what lies underneath it.&lt;/p&gt;
&lt;p&gt;Have you come across &lt;code&gt;:=&lt;/code&gt; operator in R? &lt;code&gt;:=&lt;/code&gt;, with no &lt;code&gt;%&lt;/code&gt; around it? You probably have seen if you are using &lt;em&gt;data.table&lt;/em&gt; or some rlang magic. So have I. However, I took it for granted that its operator existence is due to non-standard evaluation since it is always used within some specific context (similarly to my previously shown &lt;code&gt;%?%&lt;/code&gt; operator). I was astonished to find out that I can define this.&lt;/p&gt;
&lt;p&gt;You can write something like this.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`:=` &amp;lt;- function(lhs, rhs) lhs + 5 * rhs
2 := 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 12&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;em&gt;it works&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I told you earlier that overriding built-in operators is a &lt;em&gt;big no-no&lt;/em&gt;. What is the difference with this one? Well, &lt;strong&gt;there is no such operator in base R!&lt;/strong&gt; It turns out that &lt;code&gt;:=&lt;/code&gt; is reserved for legacy reasons, and the parser still treats it as a single operator. (You can try creating similar functions for other strings – you won’t make R treat them as infix operators without percent signs, they need to be reserved.) Yet &lt;code&gt;:=&lt;/code&gt; has no definition in base. You can read more on &lt;a href=&#34;https://stackoverflow.com/questions/32817780/what-is-the-r-assignment-operator-for&#34;&gt;the SO thread about this operator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to be fancy, you can assign a classic assignment operator to this one and make others wonder how.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`:=` &amp;lt;- `&amp;lt;-`
a := 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(But seriously: don’t do it.)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;send-the-letter&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Send the letter!&lt;/h1&gt;
&lt;p&gt;The ability to create your custom inter-argument operators is an exquisite addition to the language. They can make the code much more readable and, usually, shorter. I strongly encourage you to take advantage of the language’s possibilities and play around with it. Since it’s your working tool, let’s make using it as enjoyable as possible!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Case Study: Modularizing a Package</title><enclosure url="https://turtletopia.github.io/images/logo.png" type="image/jpg"></enclosure>
      <link>https://turtletopia.github.io/2022/08/04/case-study-modularizing-a-package/</link>
      <pubDate>Thu, 04 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/08/04/case-study-modularizing-a-package/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#origins-of-deepdep&#34; id=&#34;toc-origins-of-deepdep&#34;&gt;Origins of deepdep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#separation-of-woodendesc&#34; id=&#34;toc-separation-of-woodendesc&#34;&gt;Separation of woodendesc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#a-new-package-is-not-always-the-answer&#34; id=&#34;toc-a-new-package-is-not-always-the-answer&#34;&gt;A new package is not always the answer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#modularization-of-tidysq&#34; id=&#34;toc-modularization-of-tidysq&#34;&gt;Modularization of tidysq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#summary&#34; id=&#34;toc-summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;“Would it be possible…?”, “I think it would be nice if…”, “Can you implement…?”.&lt;/p&gt;
&lt;p&gt;User feedback is a reliable source of valuable ideas for package improvement, but it’s easy to get too eager and implement everything the users want, especially when you’ve only started making a name for yourself. I and Dominik have fallen victim to that too.&lt;/p&gt;
&lt;div id=&#34;origins-of-deepdep&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Origins of deepdep&lt;/h2&gt;
&lt;p&gt;Our package &lt;a href=&#34;https://github.com/DominikRafacz/deepdep&#34;&gt;deepdep&lt;/a&gt; was initially created as a university project. There were four of initial authors: the two of us and our colleagues, Hubert and Szymon. The teacher had a use case in mind (creating layered dependency plots) and we wanted to implement all that could get us a good grade. So we added everything more or less related to dependency plots that we could implement at the time.&lt;/p&gt;
&lt;p&gt;Fast forward a few years and a question came up regarding using a repository mirror other than the CRAN mirror we hardcoded. The function in question? &lt;code&gt;get_available_packages()&lt;/code&gt;. We’ve exchanged a few messages and it turned out that &lt;code&gt;get_available_packages()&lt;/code&gt; only served as a safeguard against using other mirrors within &lt;code&gt;deepdep()&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;In fact, the whole backend that downloads the data needed a rewrite. &lt;code&gt;get_dependencies()&lt;/code&gt; tried to provide a unified API for retrieving dependencies from different sources and &lt;code&gt;get_descriptions()&lt;/code&gt; did the same for DESCRIPTION… but they ended up messy and counterintuitive. The user could only get data from CRAN, CRAN with Bioconductor, or from the local library that was first in &lt;code&gt;.localPaths()&lt;/code&gt;. No handling Bioconductor only, no using CRAN as a fallback for local library, no querying other repositories (e.g. R-universe). The functions had to grow a lot if we wanted them to be as universal as possible.&lt;/p&gt;
&lt;p&gt;The other issue made us realize that the plotting feature is optional to some; that the key feature is collecting dependency data in a table, which only needs a small fraction of dependencies (&lt;a href=&#34;https://github.com/r-lib/httr&#34;&gt;httr&lt;/a&gt; and &lt;a href=&#34;https://github.com/jeroen/jsonlite&#34;&gt;jsonlite&lt;/a&gt;). We moved a lot of previous Imports to Suggests (&lt;a href=&#34;https://github.com/tidyverse/ggplot2&#34;&gt;ggplot2&lt;/a&gt;, &lt;a href=&#34;https://github.com/thomasp85/ggraph&#34;&gt;ggraph&lt;/a&gt;, &lt;a href=&#34;https://github.com/schochastics/graphlayouts&#34;&gt;graphlayouts&lt;/a&gt;, &lt;a href=&#34;https://github.com/igraph/rigraph&#34;&gt;igraph&lt;/a&gt;, and &lt;a href=&#34;https://github.com/r-lib/scales&#34;&gt;scales&lt;/a&gt;), lightening deepdep significantly… but that’s a topic for another post.&lt;/p&gt;
&lt;p&gt;It was time to ask ourselves: “what does «deepdep» mean to us?”. The answer was: “it’s a package that helps with analyzing and visualizing hierarchy of package dependencies”. No more, no less. The functions that extracted dependencies of a package or a DESCRIPTION file were just tools to accomplish that goal. They were exported because “we couldn’t let a good function go to waste”, not because they presented a functionality we wanted to provide. If a user would want to use one of these, they’d have to install the whole deepdep; it would be like installing ggplot2 for &lt;code&gt;cut_interval()&lt;/code&gt; and &lt;code&gt;cut_width()&lt;/code&gt; instead of plotting.&lt;/p&gt;
&lt;p&gt;The time has come for a separation.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;separation-of-woodendesc&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Separation of woodendesc&lt;/h2&gt;
&lt;p&gt;The idea is to modularize – to allow the user to install what they want. If they want to retrieve a list of dependencies for one package or a list of available packages in a repository, they should not need to install deepdep. They should be able to install a separate package that deepdep imports: &lt;a href=&#34;https://github.com/turtletopia/woodendesc&#34;&gt;woodendesc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This package is a complete rewrite of these functionalities, but much more flexible and much more potent. To show the difference, this is how you’d get packages available on CRAN and Bioconductor in old deepdep:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Hey, a wild R 4.1.0 pipe appeared!
deepdep::get_available_packages(bioc = TRUE) |&amp;gt;
  head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;A3&amp;quot;        &amp;quot;a4&amp;quot;        &amp;quot;a4Base&amp;quot;    &amp;quot;a4Classif&amp;quot; &amp;quot;a4Core&amp;quot;    &amp;quot;a4Preproc&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can’t do much more than that. The only other option is to get locally available packages. This is the signature of the function:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;get_available_packages &amp;lt;- function(
  bioc = FALSE, local = FALSE, reset_cache = FALSE
) {
  # Implementation goes here
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But woodendesc goes three steps further. There are functions for many different sources of packages, each of them optimized for minimal network usage and maximal cache utilization:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Simple CRAN extractor
woodendesc::wood_cran_packages()
# Allows `release` parameter to query old releases
woodendesc::wood_bioc_packages()
# The user can specify different paths
woodendesc::wood_local_packages()
# Functions below not possible in old deepdep:
woodendesc::wood_runiverse_packages(&amp;quot;turtletopia&amp;quot;)
woodendesc::wood_url_packages(&amp;quot;http://www.omegahat.net/R&amp;quot;)
woodendesc::wood_core_packages()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you’d want a single function like &lt;code&gt;get_available_packages()&lt;/code&gt;? Easy, just call &lt;code&gt;wood_packages()&lt;/code&gt; with specified repos (by default it only queries CRAN):&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;woodendesc::wood_packages(c(&amp;quot;bioc&amp;quot;, &amp;quot;cran&amp;quot;)) |&amp;gt;
  head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;A3&amp;quot;        &amp;quot;a4&amp;quot;        &amp;quot;a4Base&amp;quot;    &amp;quot;a4Classif&amp;quot; &amp;quot;a4Core&amp;quot;    &amp;quot;a4Preproc&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can do it with all the sources above and even pass most parameters:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;woodendesc::wood_packages(
  c(&amp;quot;bioc@1.5&amp;quot;, &amp;quot;core&amp;quot;, &amp;quot;runiverse@turtletopia&amp;quot;,
    &amp;quot;http://www.omegahat.net/R&amp;quot;, &amp;quot;local#all&amp;quot;)
) |&amp;gt;
  head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;00LOCK-lubridate&amp;quot; &amp;quot;aCGH&amp;quot;             &amp;quot;affy&amp;quot;             &amp;quot;affycomp&amp;quot;        
## [5] &amp;quot;affydata&amp;quot;         &amp;quot;affylmGUI&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you can see why’d we separate these functionalities into a new package. There are analogous functions for version codes and dependencies (about 20 functions total!) and they’d overwhelm the original intent of deepdep. Adding woodendesc as a dependency of a deepdep costs nothing because the alternative is to include this code within deepdep itself – so it’d have to be tested and maintained anyways.&lt;/p&gt;
&lt;p&gt;But sometimes modularizing is a bit extra.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-new-package-is-not-always-the-answer&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A new package is not always the answer&lt;/h2&gt;
&lt;p&gt;If you have a function if your package that doesn’t fit the general idea, don’t rush to move it into a separate package. There’s one important question to ask before:&lt;/p&gt;
&lt;p&gt;“Will it be used by anything else than my package?”&lt;/p&gt;
&lt;p&gt;And don’t be proactive here. If your answer is: “not right now, but perhaps in the future…”, just wait for the future. Keep the function in the package until the time comes and simply remove or deprecate it then (depending on how popular it gets).&lt;/p&gt;
&lt;p&gt;There’s one such functionality in deepdep: &lt;code&gt;get_downloads()&lt;/code&gt; and &lt;code&gt;plot_downloads()&lt;/code&gt;. Analyzing download statistics is not exactly the goal of deepdep, but there’s no point in making it into a separate package; these two don’t introduce any new dependencies nor do they crowd the namespace. And no one expressed any interest in having it separate from deepdep yet.&lt;/p&gt;
&lt;p&gt;Besides, nobody &lt;a href=&#34;https://github.com/eddelbuettel/digest&#34;&gt;creates a package around a single function&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;modularization-of-tidysq&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Modularization of tidysq&lt;/h2&gt;
&lt;p&gt;You might have noticed that woodendesc consists of functions that served as a backbone of deepdep while querying and plotting download statistics are more of an extension. There’s one package we’ve created that was planned to be extended since the beginning: &lt;a href=&#34;https://github.com/BioGenies/tidysq&#34;&gt;tidysq&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s a package that compresses biological sequences (e.g. DNA/RNA) by coding each letter with fewer bits (3 in DNA/RNA case). We’ve included a few basic operations like reversing, subsetting, translating to amino acids, and reading a FASTA file – the most common file format for biological sequences. We’ve intentionally omitted many more advanced functions, though.&lt;/p&gt;
&lt;p&gt;Why? Because there are countless functions and algorithms we could implement and that’d make tidysq huge. Instead, we’d gone the route of modularization. The idea is to have tidysq with the base functionality and several packages depending on tidysq, oriented towards certain aspects of working with biological sequences.&lt;/p&gt;
&lt;p&gt;For example, if we were to create a set of &lt;code&gt;read_x()&lt;/code&gt; and &lt;code&gt;write_x()&lt;/code&gt; functions for various formats like FASTQ or BAM/SAM, we’d place it in a separate package that’d have tidysq in Depends (and LinkingTo) fields. We’d call it something like “tidysqfiles” to signify that it’s an extension to tidysq.&lt;/p&gt;
&lt;p&gt;(We may or may not be working on such a package.)&lt;/p&gt;
&lt;p&gt;If you want to see a real-life example of a package ecosystem, see &lt;a href=&#34;https://mlr3verse.mlr-org.com&#34;&gt;mlr3 and mlr3verse&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;In short, there are two cases where modularization should be considered:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;strong&gt;the backend to the main functionality grows and overshadows the rest of the package&lt;/strong&gt; – create a set of logically related backend functions, move them into a new package, and add that package to Imports of the old one;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;there’s an optional functionality that requires additional imports or significantly increases the weight of the package&lt;/strong&gt; – collect several such functionalities so that they are somewhat related, move them into a new package, and add the old package to the Imports/Depends field of the new one.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Be wary of separation if the only use case for the new package is to be imported by the old one. Avoid it if there are too few functionalities for a new package. Sometimes copying a function or two isn’t a sin.&lt;/p&gt;
&lt;p&gt;Do you want to borrow &lt;a href=&#34;https://github.com/turtletopia/woodendesc/blob/master/R/wrrr.R&#34;&gt;a code that shows an install prompt for a missing package&lt;/a&gt;?&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Ice Cream for R Programmers</title><enclosure url="icecream.png" type="image/jpg"></enclosure>
      
      <link>https://turtletopia.github.io/2022/07/28/ice-cream-for-r-programmers/</link>
      <pubDate>Thu, 28 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/07/28/ice-cream-for-r-programmers/</guid>
      <description>


&lt;div id=&#34;what-and-why-ice-cream-is.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What and why ice cream is.&lt;/h1&gt;
&lt;p&gt;This post - perhaps contrary to the headline - will not be about eating ice cream. It will, however, be about something we all do too. About something, we do too often, even though we shouldn’t. About debugging with a &lt;code&gt;print()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s face it; it happens to us. We have a rich arsenal to fight bugs. We have error messages, advanced tracebacks from rlang, classic &lt;code&gt;browser()&lt;/code&gt; and &lt;code&gt;debug()&lt;/code&gt; functions, logging utilities or IDE built-in breakpoints. And yet. In our code, there happen to be code snippets scattered here and there like the following:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;some_advanced_function &amp;lt;- function(x) {
  print(&amp;quot;HERE&amp;quot;)
  y &amp;lt;- other_function(x)
  print(y)
  more_calculations()
  print(&amp;quot;I HOPE IT GETS THERE!!!!&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’re all lazy, and that’s why we use &lt;strong&gt;print-driven debugging&lt;/strong&gt; (and I’m sure I’ll expand on the laziness at another time). (It’s funny that acutely lazy evaluation is an acutely brilliant solution.) All the other solutions mentioned above require a little more effort, whereas adding a &lt;code&gt;print()&lt;/code&gt; call to the code is almost effortless. &lt;strong&gt;Almost&lt;/strong&gt;. As it usually turns out, the devil is in the detail.&lt;/p&gt;
&lt;p&gt;Since we all do it and we all consider it to be a kind of inappropriate practice, perhaps it would be worth taking some steps to make it more appropriate after all? And at the same time, pay even more tribute to our laziness? That was the idea behind the developer of the &lt;a href=&#34;https://github.com/gruns/icecream&#34;&gt;Python library IceCream&lt;/a&gt;. And this is the idea that guided me and &lt;a href=&#34;https://github.com/lewinfox&#34;&gt;Lewin Appleton-Fox&lt;/a&gt; in creating &lt;a href=&#34;https://github.com/lewinfox/icecream&#34;&gt;R version of icecream&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;how-to-eat-ice-cream-and-why-you-should-do-it.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;How to eat ice cream and why you should do it.&lt;/h1&gt;
&lt;p&gt;The most basic usage is straightforward. The library’s primary function is &lt;code&gt;ic()&lt;/code&gt;, which takes an argument of any kind, prints its value to the screen and returns it invisibly.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(icecream)

ic(12)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## ℹ ic| `12`: num 12&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can immediately see the first advantage over print: &lt;strong&gt;typing &lt;code&gt;ic()&lt;/code&gt; is faster than typing “print”&lt;/strong&gt;. Since we are here because we like to make our life more convenient, that might be important to one.&lt;/p&gt;
&lt;p&gt;That would be useless, though, if we could not include it within a function. And of course, we can do it. We will reuse the previous example but replace the &lt;code&gt;print()&lt;/code&gt; calls with &lt;code&gt;ic()&lt;/code&gt;. And let’s pack the function and other functions into an external file called &lt;code&gt;external.R&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# external.R

other_function &amp;lt;- function(x) x * 5 - 7
more_calculations &amp;lt;- function() NULL

some_advanced_function &amp;lt;- function(x) {
  ic(&amp;quot;HERE&amp;quot;)
  y &amp;lt;- other_function(x)
  ic(y)
  more_calculations()
  ic(&amp;quot;I HOPE IT GETS THERE!!!!&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;source(&amp;quot;external.R&amp;quot;)
some_advanced_function(42)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## ℹ ic| `&amp;quot;HERE&amp;quot;`: chr &amp;quot;HERE&amp;quot;
## ℹ ic| `y`: num 203
## ℹ ic| `&amp;quot;I HOPE IT GETS THERE!!!!&amp;quot;`: chr &amp;quot;I HOPE IT GETS THERE!!!!&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That works well. And you can also see another reason to use &lt;code&gt;ic()&lt;/code&gt;: &lt;strong&gt;it automatically prints expression alongside its value&lt;/strong&gt;. That might be very useful, especially if we have many prints and don’t want to check which one corresponds to which value.&lt;/p&gt;
&lt;p&gt;But, as you have probably noticed, this verbose printing introduces redundancy when printing &lt;em&gt;HERE&lt;/em&gt; etc. Well, that is on purpose. With icecream &lt;em&gt;you don’t need to provide a message to get the context&lt;/em&gt;. Let’s modify the function slightly and remove those locator messages.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# external_2.R

some_advanced_function_2 &amp;lt;- function(x) {
  ic()
  y &amp;lt;- other_function(x)
  ic(y)
  more_calculations()
  ic()
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;source(&amp;quot;external_2.R&amp;quot;)
some_advanced_function_2(42)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;ℹ ic| `some_advanced_function_2()` in external_2.R:3:2
ℹ ic| `y`: num 203
ℹ ic| `some_advanced_function_2()` in external_2.R:7:2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can see that &lt;code&gt;ic()&lt;/code&gt; is even more clever! &lt;strong&gt;It includes as precise information about the file and position in the file as possible if you call it without arguments.&lt;/strong&gt; This context inclusion makes debugging even more seamless!&lt;/p&gt;
&lt;p&gt;When the context of the file is not available (e.g. when calling a function created from a console), an environment of the source is printed:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a_function &amp;lt;- function(x) {
  x + 2
  ic()
}

a_function(0)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## ℹ ic| `a_function()` in &amp;lt;env: global&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;em&gt;Side note:&lt;/em&gt; I need to admit that I lied a little with the above code: compiling this code with R markdown does not preserve the file names when sourcing. The output is pasted manually because that would call it from the console. knitr removes references when calling &lt;code&gt;source&lt;/code&gt;, and we have not found a way around it. But that is not a concern since Rmd documents are usually final results.)&lt;/p&gt;
&lt;p&gt;What is the biggest problem with &lt;em&gt;print-driven debugging&lt;/em&gt;? Our memory. It might be a problem if we forget to remove those &lt;code&gt;print()&lt;/code&gt;s. Especially when, being irritated, we include some curse words here. And then send it to the client (anticipating questions: I have not done that, but my colleague has…). Thankfully, &lt;code&gt;ic()&lt;/code&gt; is help here! It is enough to call:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ic_disable()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to disable all the &lt;code&gt;ic()&lt;/code&gt; calls. They behave just like a regular &lt;code&gt;identity()&lt;/code&gt; now. There is a counterpart, &lt;code&gt;ic_enable()&lt;/code&gt;, which does the opposite. If you are, for example, building a shiny app, you can enable and disable &lt;code&gt;ic()&lt;/code&gt; conditionally depending on whether your app is in development or production mode. Additionally, using &lt;code&gt;ic()&lt;/code&gt; when building a package is a safety net. If you don’t import the &lt;code&gt;ic()&lt;/code&gt; function and rely solely on loading the library externally, the package will not pass checks.&lt;/p&gt;
&lt;p&gt;Last and not least, there is a &lt;strong&gt;dose of customization possibilities.&lt;/strong&gt; You can e.g. change the function used to peek and the number of lines printed, as you can see in the chunk below:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# standard settings:
ic(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## ℹ ic| `mtcars`: data.frame [32 x 11]: $&amp;#39;mpg&amp;#39;: dbl [32], $&amp;#39;cyl&amp;#39;: dbl [32], ...&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# modified settings:
options(icecream.max.lines = 5)
options(icecream.peeking.function = head)

ic(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## ℹ ic| `mtcars`: 
## mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;a-few-words-on-ice-cream-production.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A few words on ice cream production.&lt;/h1&gt;
&lt;p&gt;The inner workings of icecream are pretty curious, and I encourage you heavily to explore &lt;a href=&#34;https://github.com/lewinfox/icecream/blob/master/R/ic.R&#34;&gt;the code&lt;/a&gt; if you want to see &lt;a href=&#34;https://rlang.r-lib.org/&#34;&gt;rlang&lt;/a&gt; in action. I will comment on a few code snippets to give you a glimpse.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;ic()&lt;/code&gt; is possible because we can suspend the evaluation of arguments:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ic &amp;lt;- function(x) {
  # capture the input to allow us to work with the expression and value separately
  q &amp;lt;- rlang::enquo(x)
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;q&lt;/code&gt; holds &lt;strong&gt;the expression&lt;/strong&gt; alongside with its &lt;strong&gt;evaluation environment&lt;/strong&gt;. We can quickly transform it into a string by &lt;strong&gt;deparsing it&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deparsed_expression &amp;lt;- rlang::expr_deparse(rlang::quo_get_expr(q))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the value of the expression, we can enforce &lt;strong&gt;evaluation&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;x &amp;lt;- rlang::eval_tidy(q)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Getting the precise location of the &lt;code&gt;ic()&lt;/code&gt; call is more tricky. We can do it, however, with the usage of rlang functions for analyzing the &lt;strong&gt;stack of calls&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# this code is simplified and not guaranteed always to work

# inspecting the traceback and extracting the call stack:
trace &amp;lt;- rlang::trace_back()
call_stack &amp;lt;- trace$call

# getting length of the call stack:
num_calls &amp;lt;- length(call_stack)

# accessing the second-to-last call (to omit the `ic` call) and extracting parent reference:
parent_ref &amp;lt;- call_stack[[num_calls - 1]][[1]]

# extracting location from the reference:
ref &amp;lt;- attr(call_stack[[num_calls]], &amp;quot;srcref&amp;quot;)
loc &amp;lt;- rlang:::src_loc(ref)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that &lt;code&gt;rlang:::src_loc()&lt;/code&gt; is not an exported function, as it is not meant for end users of the package. We allowed ourselves to borrow the code of the function as it is crucial for our package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;plans-for-the-ice-cream-industry-and-conclusion.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Plans for the ice cream industry and conclusion.&lt;/h1&gt;
&lt;p&gt;If you practice using print to debug your programs, do it with class. That is what icecream offers. Its main advantages are less typing, convenient information printing, the inclusion of context, easy disabling and customization. The package is still under development, and our current goal is to fully implement the original Python version’s functionalities. I encourage you to give it a try!&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you have any suggestions for the &lt;a href=&#34;https://github.com/lewinfox/icecream&#34;&gt;icecream&lt;/a&gt;, do not hesitate to leave an issue on our repo.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Overview: Sorting Version Codes</title><enclosure url="https://turtletopia.github.io/images/logo.png" type="image/jpg"></enclosure>
      <link>https://turtletopia.github.io/2022/07/16/overview-sort-version-codes/</link>
      <pubDate>Sat, 16 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/07/16/overview-sort-version-codes/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#problem-statement&#34;&gt;Problem statement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solutions&#34;&gt;Solutions&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#using-base-r&#34;&gt;Using base R&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-gtools&#34;&gt;Using gtools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-naturalsort&#34;&gt;Using naturalsort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-stringrstringi&#34;&gt;Using stringr/stringi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-versionsort&#34;&gt;Using versionsort&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#semantic-version-codes&#34;&gt;Semantic version codes&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#using-semver&#34;&gt;Using semver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-semverutils&#34;&gt;Using semverutils&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div id=&#34;problem-statement&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem statement&lt;/h2&gt;
&lt;p&gt;Different versions of software are traditionally described using version codes. These codes contain usually numerical values and subsequent versions increment these codes, allowing them to be sorted. The standard is to use “&lt;a href=&#34;https://semver.org&#34;&gt;semantic versioning&lt;/a&gt;”, where codes are in the form of “major.minor.patch”; the bigger the update, the more important number is incremented.&lt;/p&gt;
&lt;p&gt;However, not all software obey semantic versioning standard.&lt;/p&gt;
&lt;p&gt;Suppose we have a vector of version codes:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;codes &amp;lt;- c(&amp;quot;1.2&amp;quot;, &amp;quot;1.10&amp;quot;, &amp;quot;1.1&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’d expect them to be ordered as 1.1, 1.2, 1.10. If you try to order version codes using base &lt;code&gt;sort()&lt;/code&gt; functionality…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(codes)
## [1] &amp;quot;1.1&amp;quot;  &amp;quot;1.10&amp;quot; &amp;quot;1.2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…oh. Where did something go wrong?&lt;/p&gt;
&lt;p&gt;This is what’s called “alphabetical sorting”. It checks characters one by one, including digits. “1” is before “2”, so “10” goes before “2”, no matter the value. Thus, it cannot compare numbers, if they have a different number of digits.&lt;/p&gt;
&lt;p&gt;Numerous software uses the following trick to have it sort correctly: it pads the numbers with leading 0’s until a certain length. For example, your old camera could name photos like &lt;code&gt;00034.jpg&lt;/code&gt;, &lt;code&gt;00164.jpg&lt;/code&gt;, etc. But this is not the approach to use here. We need a different one.&lt;/p&gt;
&lt;p&gt;Sorting version codes requires using something called “natural sort”, where numbers are detected and ordered according to their value (with letters still sorted alphabetically, thus placing e.g. “a99” before “b51”). This is a more intuitive sorting for humans than pure alphabetical sort.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solutions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;Several packages allow natural sorting of character vectors. There’s even a base R solution! However, not all natural sorting algorithms are adapted to handle version codes, which (usually) have a particular structure with dots and/or dashes. Let’s have a look at the options.&lt;/p&gt;
&lt;div id=&#34;using-base-r&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using base R&lt;/h3&gt;
&lt;p&gt;There’s a facility in base R allowing the user to handle (numeric) version codes. While there is no simple “sort these strings like they were version codes” function, you can wrap your vector in &lt;code&gt;numeric_version()&lt;/code&gt; and use associated methods, like comparison operators (&lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;…), as well as &lt;code&gt;sort()&lt;/code&gt; method for this class. This is what it looks like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(numeric_version(codes))
## [1] &amp;#39;1.1&amp;#39;  &amp;#39;1.2&amp;#39;  &amp;#39;1.10&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are two main problems with this approach, however. But first, let’s quote the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Numeric versions are sequences of one or more non-negative integers, usually (…) represented as character strings with the elements of the sequence concatenated and separated by single . or - characters.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This means that version codes cannot have any string components or non-standard separators. As described in the semantic versioning standard, letters are allowed in pre-release identifiers and build metadata, so the base solution cannot even handle all valid cases of semantic versioning, much less the variety of version codes that don’t fit these rules.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-gtools&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using gtools&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/r-gregmisc/gtools&#34;&gt;gtools&lt;/a&gt; is a collection of functions to help with simple tasks when writing R packages. It has a &lt;code&gt;mixedsort()&lt;/code&gt; function that detects embedded numbers in strings. However…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;gtools::mixedsort(codes)
## [1] &amp;quot;1.10&amp;quot; &amp;quot;1.1&amp;quot;  &amp;quot;1.2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…it is not suited to sorting version codes. The use case here is different, it’s detecting numbers like these in “Aspirin 50mg” and “Aspirin 100mg” (examples taken from the documentation). Dots in version codes are treated as decimal separators, that’s why &lt;code&gt;&#34;1.10&#34;&lt;/code&gt; and &lt;code&gt;&#34;1.1&#34;&lt;/code&gt; are considered equal.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-naturalsort&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using naturalsort&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/kos59125/naturalsort&#34;&gt;naturalsort&lt;/a&gt; isn’t written specifically for sorting version codes either, but…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;naturalsort::naturalsort(codes)
## [1] &amp;quot;1.1&amp;quot;  &amp;quot;1.2&amp;quot;  &amp;quot;1.10&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…it gets the job done. The difference lies in not treating dots as decimal separators (in fact, naturalsort doesn’t recognize decimals at all). Instead, the code detects numbers and non-numbers, then splits the strings into continuous pieces of numbers and non-numbers. If we were to For example, &lt;code&gt;&#34;1.10-a&#34;&lt;/code&gt; would be split like that:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;split_like_naturalsort(&amp;quot;1.10-a&amp;quot;)
## [1] &amp;quot;1&amp;quot;  &amp;quot;.&amp;quot;  &amp;quot;10&amp;quot; &amp;quot;-a&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These pieces are then used to sort version codes either alphabetically or by value, depending on whether it’s a number or not. Accidentally, this works well for almost all version codes. The only case where it’s working a little weird is when there’s an inconsistency in separators:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;weird_codes &amp;lt;- c(&amp;quot;1.3-6&amp;quot;, &amp;quot;1.3-2&amp;quot;, &amp;quot;1.3.4&amp;quot;)
naturalsort::naturalsort(weird_codes)
## [1] &amp;quot;1.3-2&amp;quot; &amp;quot;1.3-6&amp;quot; &amp;quot;1.3.4&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I like that naturalsort has &lt;code&gt;decreasing&lt;/code&gt; and &lt;code&gt;na.last&lt;/code&gt; parameters, implemented just like in base &lt;code&gt;sort()&lt;/code&gt;. There’s also a &lt;code&gt;naturalfactor()&lt;/code&gt; function that could be useful for long vectors of repeated version codes.&lt;/p&gt;
&lt;p&gt;naturalsort isn’t developed since 2016, but this shouldn’t be considered a problem, since the package is in an already stable state. There’s one pet peeve of mine about this package and it’s the implicit coercion of parameters. Let’s say we accidentally made this call:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;naturalsort::naturalsort(codes,
                         decreasing = c(&amp;quot;true&amp;quot;, &amp;quot;dat&amp;quot;))
## [1] &amp;quot;1.10&amp;quot; &amp;quot;1.2&amp;quot;  &amp;quot;1.1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out &lt;code&gt;c(&#34;true&#34;, &#34;dat&#34;)&lt;/code&gt; was coerced to logical, then the first element was taken. It should raise an error saying that the arguments are wrong, but – instead – it tries to work at all costs, over-interpreting the parameters. A similar thing would happen with a vector of logical values.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-stringrstringi&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using stringr/stringi&lt;/h3&gt;
&lt;p&gt;You’ve probably already installed &lt;a href=&#34;https://github.com/tidyverse/stringr&#34;&gt;stringr&lt;/a&gt; and/or &lt;a href=&#34;https://github.com/gagolews/stringi&#34;&gt;stringi&lt;/a&gt; if you’ve been using R for a while. Both these packages can do way, way more to strings than just some natural sorting, but we’ll focus on just that. There’s a parameter called &lt;code&gt;numeric&lt;/code&gt; in &lt;code&gt;stri_sort()&lt;/code&gt;, where we can pass &lt;code&gt;TRUE&lt;/code&gt; to sort digits numerically:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# There&amp;#39;s analogous stringr::str_sort() function
stringi::stri_sort(codes, numeric = TRUE)
## [1] &amp;quot;1.1&amp;quot;  &amp;quot;1.2&amp;quot;  &amp;quot;1.10&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The overall implementation seems to base on the same idea of separating numbers and non-numbers, and it has the same behavior on inconsistent separators:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;stringi::stri_sort(weird_codes, numeric = TRUE)
## [1] &amp;quot;1.3-2&amp;quot; &amp;quot;1.3-6&amp;quot; &amp;quot;1.3.4&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are &lt;code&gt;decreasing&lt;/code&gt; and &lt;code&gt;na_last&lt;/code&gt; parameters just like in &lt;code&gt;naturalsort()&lt;/code&gt; and base &lt;code&gt;sort()&lt;/code&gt;; and again, there’s silent argument coercion I despise. At least I can give half a point for raising a warning when only the first element is used.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-versionsort&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using versionsort&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/turtletopia/versionsort&#34;&gt;versionsort&lt;/a&gt; is our solution to this problem. I’ve implemented, documented, tested, and submitted it to CRAN within 24 hours when working on implementing a feature in &lt;a href=&#34;https://github.com/DominikRafacz/deepdep&#34;&gt;deepdep&lt;/a&gt;; obviously, it has changed a bit since then.&lt;/p&gt;
&lt;p&gt;There’s a &lt;code&gt;ver_sort()&lt;/code&gt; function that’s of the main interest here:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;versionsort::ver_sort(codes)
## [1] &amp;quot;1.1&amp;quot;  &amp;quot;1.2&amp;quot;  &amp;quot;1.10&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It works a little differently than other sorts I’ve mentioned before, as it splits the string on separators first (which are sequences of anything that is not a number or a letter), only then separating numbers and non-numbers (i.e. letters). All separators are equal, which gives a little more predictable behavior with inconsistent separators:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;versionsort::ver_sort(weird_codes)
## [1] &amp;quot;1.3-2&amp;quot; &amp;quot;1.3.4&amp;quot; &amp;quot;1.3-6&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;versionsort is still a Work-In-Progress, which means that it lacks &lt;code&gt;decreasing&lt;/code&gt; and &lt;code&gt;na_last&lt;/code&gt; parameters, but this whole analysis serves partially to define requirements for future development (more in soon-to-be-published versionsort Dev Plan).&lt;/p&gt;
&lt;p&gt;There’s one convenient utility versionsort has, though – the pair of functions named &lt;code&gt;ver_latest()&lt;/code&gt; and &lt;code&gt;ver_oldest()&lt;/code&gt;. They return &lt;code&gt;max()&lt;/code&gt; and &lt;code&gt;min()&lt;/code&gt; for version codes, respectively, without the need for sorting the whole vector:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;versionsort::ver_latest(codes)
## [1] &amp;quot;1.10&amp;quot;
versionsort::ver_oldest(codes)
## [1] &amp;quot;1.1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Stay tuned for the new, improved versionsort!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;semantic-version-codes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Semantic version codes&lt;/h2&gt;
&lt;p&gt;All these solutions have one thing in common – they don’t detect semantic version codes. There are, however, R packages with this functionality; I’ve found two, described below.&lt;/p&gt;
&lt;div id=&#34;using-semver&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using semver&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/johndharrison/semver&#34;&gt;semver&lt;/a&gt; is the most used R package for handling semantic version codes. It relies heavily on &lt;a href=&#34;https://github.com/zmarko/semver&#34;&gt;C++ semver&lt;/a&gt; implementation under the hood, but it results in a wide range of functionalities: there are many methods for parsed semantic codes, &lt;code&gt;sort()&lt;/code&gt; included:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;semver_codes &amp;lt;- semver::parse_version(
  c(&amp;quot;1.6.0-dev&amp;quot;, &amp;quot;1.5.10&amp;quot;, &amp;quot;1.5.1&amp;quot;, &amp;quot;1.6.0&amp;quot;)
)
sort(semver_codes)
## [1] Maj: 1 Min: 5 Pat: 1
## 
## [2] Maj: 1 Min: 5 Pat: 10
## 
## [3] Maj: 1 Min: 6 Pat: 0 Pre: dev
## 
## [4] Maj: 1 Min: 6 Pat: 0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Operators as well:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;semver_codes[1:3] &amp;lt; semver_codes[2:4]
## [1] FALSE FALSE  TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use &lt;code&gt;max()&lt;/code&gt; and &lt;code&gt;min()&lt;/code&gt; too:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;max(semver_codes)
## Maj: 1 Min: 6 Pat: 0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This package has the most functionality of them all…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;semver::parse_version(&amp;quot;1.0-10&amp;quot;)
## Error in parse_ptr(version): invalid character encountered: -&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…but is nonetheless limited to semantic version codes.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-semverutils&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using semverutils&lt;/h3&gt;
&lt;p&gt;Sorting numeric codes is not possible in &lt;a href=&#34;https://github.com/ajwtech/semverutils&#34;&gt;semverutils&lt;/a&gt;. You can only check if a version code is higher than others by calling:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v_code &amp;lt;- semverutils::semVer$new(c(&amp;quot;1.6.0-dev&amp;quot;))
v_code$higherThanAll(c(&amp;quot;1.5.10&amp;quot;, &amp;quot;1.6.0&amp;quot;, &amp;quot;1.5.1&amp;quot;))
## [1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, the answer isn’t even correct, since &lt;code&gt;&#34;1.6.0-dev&#34;&lt;/code&gt; precedes &lt;code&gt;&#34;1.6.0&#34;&lt;/code&gt; due to being a pre-release version.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There are a few ways to sort version codes. If your version codes are simple and well-behaved, &lt;code&gt;base::numeric_version()&lt;/code&gt; should be enough. If you need to handle semantic version codes, use &lt;a href=&#34;https://github.com/johndharrison/semver&#34;&gt;semver&lt;/a&gt;. Otherwise, there is no best solution, but &lt;a href=&#34;https://github.com/turtletopia/versionsort&#34;&gt;versionsort&lt;/a&gt; is the closest you can get, especially after the next big update is published.&lt;/p&gt;
&lt;p&gt;Missed a package? Described one incorrectly? Contact us &lt;a href=&#34;https://twitter.com/Rturtletopia&#34;&gt;on Twitter&lt;/a&gt; or make an issue &lt;a href=&#34;https://github.com/turtletopia/turtletopia.github.io/issues&#34;&gt;on Github&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Shiny Reactivity Tricks, pt. I: Creating Observers in Loop</title><enclosure url="loop.png" type="image/jpg"></enclosure>
      
      <link>https://turtletopia.github.io/2022/07/09/shiny-reactivity-tricks-pt-i-creating-observers-in-loop/</link>
      <pubDate>Sat, 09 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/07/09/shiny-reactivity-tricks-pt-i-creating-observers-in-loop/</guid>
      <description>

&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#preface&#34; id=&#34;toc-preface&#34;&gt;Preface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#use-case-and-naive-solution&#34; id=&#34;toc-use-case-and-naive-solution&#34;&gt;Use case and naive solution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#a-quick-recap-of-environments&#34; id=&#34;toc-a-quick-recap-of-environments&#34;&gt;A quick recap of environments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#environments-in-shiny&#34; id=&#34;toc-environments-in-shiny&#34;&gt;Environments in Shiny&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-1-create-an-environment-for-each-observer&#34; id=&#34;toc-solution-1-create-an-environment-for-each-observer&#34;&gt;Solution 1: Create an environment for each observer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-2-inject-the-constants&#34; id=&#34;toc-solution-2-inject-the-constants&#34;&gt;Solution 2: Inject the constants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#solution-3-or-solution-suggestion-utilize-shiny-modules&#34; id=&#34;toc-solution-3-or-solution-suggestion-utilize-shiny-modules&#34;&gt;Solution 3 (or solution suggestion): Utilize Shiny modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#summary&#34; id=&#34;toc-summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div id=&#34;preface&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Preface&lt;/h1&gt;
&lt;p&gt;I’ve been recently working a lot in Shiny, and I’ve constantly been stumbling across new problems. Many of them seemed interesting enough for me to want to write an article. However, in the course of the work, I found that I had too much to write about… so I decided to break it down into a series of smaller articles linked to each other.&lt;/p&gt;
&lt;p&gt;I’ll start with something simple: creating some objects in a loop. If you think it’s too easy, wait a minute; you may be surprised! This seemingly easy task will be an excuse to understand how certain things in R and shiny work underneath, even though we ignore it daily.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;use-case-and-naive-solution&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Use case and naive solution&lt;/h1&gt;
&lt;p&gt;Let’s start with some simple examples. Like all simple examples, it may feel highly artificial, but at least it is not very complex. Let’s say that we want to have an app that has four numeric inputs. The first input allows the user to select an &lt;em&gt;Important Number&lt;/em&gt;. Other inputs… well, they are not used. But we want them to have their values updated every time the &lt;em&gt;Important Number&lt;/em&gt; is updated. And we want to have separate observers to handle them (yes, I know that one observer would work here as well… but I told you this might feel artificial!). Their values are calculated via some calculations which are entirely irrelevant right now.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(shiny)
# side note: all functions which are not prepended with scope operator 
# are either from base R or from the `shiny` package

do_calculations &amp;lt;- function(important, other) {
  # this is totally random
  (important * other * 2^5 + important - 7 * other) %% 101
}

ui &amp;lt;- fluidPage(
  numericInput(&amp;quot;important&amp;quot;, &amp;quot;Select important number&amp;quot;, 
               min = 0, max = 100, value = 42),
  numericInput(&amp;quot;var_1&amp;quot;, &amp;quot;Select input 1&amp;quot;, 
               min = 0, max = 100, value = 0),
  numericInput(&amp;quot;var_2&amp;quot;, &amp;quot;Select input 2&amp;quot;, 
               min = 0, max = 100, value = 0),
  numericInput(&amp;quot;var_3&amp;quot;, &amp;quot;Select input 3&amp;quot;, 
               min = 0, max = 100, value = 0)
)

server &amp;lt;- function(input, output, session) {
  observe({
    updateSliderInput(
      session = session,
      inputId = &amp;quot;var_1&amp;quot;,
      value = do_calculations(input[[&amp;quot;important&amp;quot;]], 1)
    )
  })

  observe({
    updateSliderInput(
      session = session,
      inputId = &amp;quot;var_2&amp;quot;,
      value = do_calculations(input[[&amp;quot;important&amp;quot;]], 2)
    )
  })

  observe({
    updateSliderInput(
      session = session,
      inputId = &amp;quot;var_3&amp;quot;,
      value = do_calculations(input[[&amp;quot;important&amp;quot;]], 3)
    )
  })
}

shinyApp(ui, server)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/observers-in-loop-peek-1.gif&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Simple version of the app.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It works like a charm! But we can easily see that there is a lot of copypasting. And copypasting is something we should avoid. (Some other day, I would love to say something more about it in general.) If you have gone so far into the article, you probably know what I want to do: a loop. There are two prominent places to use it – in UI and server. UI first, since it seems more manageable. We are R users, so we should make &lt;em&gt;real&lt;/em&gt; loops only when there are no other means. Thus we are using good old &lt;code&gt;lapply&lt;/code&gt;, as it is even simpler than trying to use &lt;em&gt;for&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ui &amp;lt;- fluidPage(
  numericInput(&amp;quot;important&amp;quot;, &amp;quot;Select important number&amp;quot;, 
               min = 0, max = 100, value = 42),
  lapply(1:3, function(i) {
    numericInput(inputId = paste0(&amp;quot;var_&amp;quot;, i), paste0(&amp;quot;Select input &amp;quot;, i), 
                 min = 0, max = 100, value = 0)
  })
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, this is simple, indeed. It works as it did without the loop; you can check on your own if you don’t believe me.&lt;/p&gt;
&lt;p&gt;Now it’s time for the server. Here we are calling &lt;code&gt;observer&lt;/code&gt; mainly for its side effect (i.e. registration of observers), so the &lt;code&gt;for&lt;/code&gt; loop might be more appropriate.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;server &amp;lt;- function(input, output, session) {
  for (i in 1:3) {
    observe({
      updateSliderInput(
        session = session,
        inputId = paste0(&amp;quot;var_&amp;quot;, i),
        value = do_calculations(input[[&amp;quot;important&amp;quot;]], i)
      )
    })
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now – something strange happens! Only the last of the observers works as expected; others seem off. If you know at first glance what happens there – congrats; you are good at R and Shiny. If you don’t know, then we need to understand what environments are relevant for Shiny.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-quick-recap-of-environments&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A quick recap of environments&lt;/h1&gt;
&lt;p&gt;Each R expression is evaluated in some &lt;strong&gt;environment&lt;/strong&gt;. An environment can be considered a list of names with associated values. There are, however, some differences, of which two are the most important:&lt;/p&gt;
&lt;p&gt;Firstly, each environment contains a &lt;strong&gt;reference to its parent&lt;/strong&gt;, so they create a tree-like structure. One exception to this rule is the &lt;em&gt;empty environment&lt;/em&gt; which does not have a parent and serves as the root of the whole hierarchy.&lt;/p&gt;
&lt;p&gt;Secondly, &lt;strong&gt;environments are mutable&lt;/strong&gt;. If you pass an environment to a function and mutate some objects inside, the values in the environments are also changed for the external viewer.&lt;/p&gt;
&lt;p&gt;Every time we create an object in R and assign its value to some time, we bind this object within some environment. Calls from the console or scripts at the top-level assign objects to &lt;em&gt;the global environment&lt;/em&gt;. Creating variables inside a function assigns them to an &lt;em&gt;execution environment&lt;/em&gt;. Each &lt;em&gt;package&lt;/em&gt; also has its environment, where all its functions and objects are available.&lt;/p&gt;
&lt;p&gt;When we want to access some variable, it is first sought in the &lt;em&gt;evaluation environment&lt;/em&gt;, i.e. the environment where this call is performed. If no object of this name is found, it is sought down the &lt;strong&gt;search path&lt;/strong&gt;: in the parent environment of the calling env, then in the parent of the parent, etc., down to the empty env. At the start of the R session, base packages are inserted into this hierarchy, so those objects are accessible from the global environment. Additionally, every time we use &lt;code&gt;library&lt;/code&gt;, the environment of the loaded package is inserted into the path. That explains why we have access to all the functions and objects from the console. That also explains why objects in the global environment are visible from within the function called in the global environment.&lt;/p&gt;
&lt;p&gt;One more thing worth mentioning – in R, we can manage the time of evaluation of the code. If a function is provided with an expression, there are means to suspend the evaluation of its arguments. Then we can modify it or evaluate it later.&lt;/p&gt;
&lt;p&gt;I won’t go into the details of how to do it right now (but don’t worry, I like the topic too much not to tell more about it). If you want to get new knowledge or refresh the one that you’ve got, you can see &lt;a href=&#34;https://adv-r.hadley.nz/environments.html&#34;&gt;a chapter in Advanced R by Hadley Wickham&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;environments-in-shiny&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Environments in Shiny&lt;/h1&gt;
&lt;p&gt;Environments are super crazy functional. The fact that they exist does Shiny work at all. And they are also the reason why our &lt;em&gt;for&lt;/em&gt; loop did not work. That is, of course, only a part of the whole picture, but such complicated topics are easier to swallow in smaller bits.&lt;/p&gt;
&lt;p&gt;We need to focus on what happens when the app starts (e.g. when function &lt;code&gt;shinyApp(ui, server)&lt;/code&gt; is called). Somewhere in the guts of Shiny, the &lt;code&gt;server&lt;/code&gt; function is called. Just as with any other function, it has its execution environment. This environment is provided with &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;output&lt;/code&gt; lists of reactive values; it also has the global environment as its ancestor (and therefore, it has access to any loaded packages). When the code inside this function is executed, objects specified by the user are created. Significantly, all reactive objects are made, and the user can modify &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;output&lt;/code&gt; reactive values. Also, our objects of focus – observers – are registered.&lt;/p&gt;
&lt;p&gt;The most crucial point is: when the &lt;code&gt;server&lt;/code&gt; function is executed, and R stumbles upon the &lt;code&gt;observer&lt;/code&gt; call, it &lt;strong&gt;does not&lt;/strong&gt; evaluate the code passed as the first argument. Instead, it registers the observer and stores the code for later evaluation. We are still at the start-up stage, and now Shiny only creates net reactive dependencies. No inputs are available; they appear just after somebody opens the browser and initializes the page. That also applies to all expressions enclosed in &lt;code&gt;reactive&lt;/code&gt;’s, &lt;code&gt;render&lt;/code&gt;’s, etc., but we skip them in the other part as they do not appear in our example.&lt;/p&gt;
&lt;p&gt;Now goes the neat part: during the application runtime, code provided to &lt;code&gt;observer&lt;/code&gt; is evaluated as is in the server function execution environment. So, when seeking a variable, it looks for its value in this environment. It does not magically replace the &lt;code&gt;i&lt;/code&gt; variable with the value used in the loop iteration, as might be expected. I made a diagram (included below) which illustrates how it &lt;strong&gt;does not&lt;/strong&gt; work.&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/observers-in-loop-observer-exp.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Expected situation&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Stating it once again: every time the observer is called, &lt;code&gt;i&lt;/code&gt; is being sought in the current or enclosing environments. But that introduces the question: shouldn’t that mean that &lt;code&gt;i&lt;/code&gt; is missing and calling &lt;code&gt;i&lt;/code&gt; raises an error? Why does it work for one of the observers? The answer is: actually, all three observers work. But they all modify the input number 3. And that is because of one quite peculiar property of R. Namely, the variable used to iterate &lt;strong&gt;is not destroyed&lt;/strong&gt; after finishing the loop execution, and it stays in the environment with the value of the last value used in the loop. In our case, &lt;code&gt;i&lt;/code&gt; exists in the server environment and has the value &lt;code&gt;3&lt;/code&gt;. See the diagram below.&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/observers-in-loop-observer-actual.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Actual situation&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As a side note, I want to add that there is also the topic of visibility of Shiny objects between users’ sessions. It is covered by &lt;a href=&#34;https://shiny.rstudio.com/articles/scoping.html&#34;&gt;an article on the official Shiny webpage&lt;/a&gt;. I strongly recommend reading it.&lt;/p&gt;
&lt;p&gt;Since we already know what happens, we must learn how to get around it. There are at least a few solutions.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-1-create-an-environment-for-each-observer&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 1: Create an environment for each observer&lt;/h1&gt;
&lt;p&gt;I told you that the code in observers etc., is evaluated in the server environment. It is true &lt;strong&gt;by default&lt;/strong&gt;. There are ways of changing it, even straightforward ways. &lt;code&gt;observer&lt;/code&gt; function has a parameter &lt;code&gt;env&lt;/code&gt;, which allows us to set the evaluation environment.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;for (i in 1:3) {
  env &amp;lt;- new.env()
  env[[&amp;quot;i&amp;quot;]] &amp;lt;- i
    
  observe({
    updateSliderInput(
      session = session,
      inputId = paste0(&amp;quot;var_&amp;quot;, i),
      value = do_calculations(input[[&amp;quot;important&amp;quot;]], i)
    )
  }, env = env)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In each loop iteration, we create a new environment whose parent is the server environment. Then we assign the current value of the &lt;code&gt;i&lt;/code&gt; to the environment and provide the env as a parameter for the observer. As a result, each observer has its environment with its own &lt;code&gt;i&lt;/code&gt; object. Those envs refer to server env as a parent, so all other variables are accessible. The trick is possible because those numerous envs are not used inside the observers’ quoted code; they are kept together with code. The concept is illustrated in the diagram below.&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;https://turtletopia.github.io/images/observers-in-loop-observer-envs.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;Solution with the creation of environments&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can also do the same with a small change. &lt;code&gt;new.env()&lt;/code&gt; call can be replaced with &lt;code&gt;rlang::env()&lt;/code&gt;. &lt;em&gt;rlang&lt;/em&gt; is a package that overhauls the interface of operating on expressions and environments in R, as base R ways of doing it are messy. A minor change, but on this blog, we will demonstrate rlang features heavily, so you should get used to it. Additional source is &lt;a href=&#34;https://rlang.r-lib.org/&#34;&gt;the project webpage&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-2-inject-the-constants&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 2: Inject the constants&lt;/h1&gt;
&lt;p&gt;Speaking of rlang… The second solution employs rlang’s features and does something very clever: it replaces a variable with a constant.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;for (i in 1:3) {
  rlang::inject({
    observe({
      updateSliderInput(
        session = session,
        inputId = paste0(&amp;quot;var_&amp;quot;, !!i),
        value = do_calculations(input[[&amp;quot;important&amp;quot;]], !!i)
      )
    })
  })
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Beautiful, isn’t it? This code looks almost the same as the code from the not-working approach of simple iteration. The first difference is prepending &lt;code&gt;i&lt;/code&gt; variable appearances with the &lt;code&gt;!!&lt;/code&gt; symbol (&lt;em&gt;bang-bang&lt;/em&gt;, as ones say, or more professionally: &lt;em&gt;unquotation symbol&lt;/em&gt;). The second is wrapping the whole observer with the &lt;code&gt;rlang::inject&lt;/code&gt; function. This function replaces everything prepended by an unquotation symbol with the value of the symbol. That operates on the level of expression. Before &lt;code&gt;observer&lt;/code&gt; is called, both appearances of &lt;code&gt;i&lt;/code&gt; are replaced with the current value of &lt;code&gt;i&lt;/code&gt;. Only after that the observer is called, and modified code is saved instead. You have to admit: this is elegant. It also makes the code work as we expected the original code to work, that is, without creating additional environments.&lt;/p&gt;
&lt;p&gt;This solution is possible with base R, but the code is significantly less appealing and easy to understand, so we will only stick to it.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-3-or-solution-suggestion-utilize-shiny-modules&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution 3 (or solution suggestion): Utilize Shiny modules&lt;/h1&gt;
&lt;p&gt;Finally, there is one more solution. If you are already familiar with &lt;em&gt;shiny modules&lt;/em&gt; then it should be clear that you can use them. I will not provide the code yet, mainly because it seems to me that many things have already happened today. But don’t worry – I have a lot to say about the modules too. We will come back to it. Those that know how they work can write code using modules as homework. Those that do not know should read some introduction to shiny modules.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Summary&lt;/h1&gt;
&lt;p&gt;When environments and modification of expressions come into play, even as simple as loops may get complicated, I wanted to show you that coming across them in R (especially in Shiny) is easy. Without a slightly more profound understanding of it, they might seem illogical and not rarely impossible to overcome. Having the additional knowledge and ability to use such tools as rlang might allow you to make your code better and cleaner. And sometimes working at all.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Hello world</title><enclosure url="https://turtletopia.github.io/images/logo.png" type="image/jpg"></enclosure>
      <link>https://turtletopia.github.io/2022/07/01/hello-world/</link>
      <pubDate>Fri, 01 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://turtletopia.github.io/2022/07/01/hello-world/</guid>
      <description>&lt;p&gt;Hi all!&lt;/p&gt;
&lt;p&gt;I think it would be some aberration to start a programming blog with a post with any other title than &amp;ldquo;Hello world&amp;rdquo;&amp;hellip;&lt;/p&gt;
&lt;p&gt;I am Dominik. I am a software developer and Data Science student (with the time of graduation approaching with high velocity). My friend Laura and I are passionate about programming in R. We love creating tools and playing with language to please others and ourselves (in any order).&lt;/p&gt;
&lt;p&gt;This blog is meant for us to write about R.&lt;/p&gt;
&lt;p&gt;(Probably not only R, but hey, this is the language we have the most experience with)&lt;/p&gt;
&lt;p&gt;We will publish here information about the open-source stuff we make. We will show some obstacles we have stumbled upon and our ways around them. We will praise the language and complain about it. We will share other cool toys we have found and love using. &lt;del&gt;We will rock you&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;You can find some of our packages in our &lt;a href=&#34;https://github.com/turtletopia&#34;&gt;GitHub organization&lt;/a&gt;. Soon there will be many rearrangements, and we will focus on finally turning our recent ideas into flesh.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>About</title><enclosure url="https://turtletopia.github.io/images/logo.png" type="image/jpg"></enclosure>
      <link>https://turtletopia.github.io/about/</link>
      <pubDate>Thu, 05 May 2016 21:48:51 -0700</pubDate>
      
      <guid>https://turtletopia.github.io/about/</guid>
      <description>&lt;p&gt;Hey, Laura and Dominik here!&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve studied and worked together on several R projects in many domains over the last few years. There were shiny apps, machine learning, bioinformatics, Rcpp, data visualization&amp;hellip; we can&amp;rsquo;t even list it all. And the time has come to share that knowledge.&lt;/p&gt;
&lt;p&gt;We want to have a few types of blog posts: some talking about our experiences with certain packages/frameworks (looking at you, shiny!), some sharing obscure knowledge and R facts, some showing how to implement something in a given framework, and some giving an overview of existing solutions to certain problems. And maybe an occasional rambling about other languages (especially C++ due to the existence of Rcpp) as well.&lt;/p&gt;
&lt;p&gt;If you have an idea for a post (especially How To and Overview post types), tag us &lt;a href=&#34;https://twitter.com/Rturtletopia&#34;&gt;on Twitter&lt;/a&gt; or make an issue &lt;a href=&#34;https://github.com/turtletopia/turtletopia.github.io/issues&#34;&gt;on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This blog uses a &lt;a href=&#34;https://github.com/rstudio/blogdown&#34;&gt;blogdown&lt;/a&gt; framework.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
