<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alberto de Murga</title>
    <description>The latest articles on DEV Community by Alberto de Murga (@threkk).</description>
    <link>https://dev.to/threkk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F24673%2Fbc1f72af-c5da-4495-b1d6-c64613104b27.JPG</url>
      <title>DEV Community: Alberto de Murga</title>
      <link>https://dev.to/threkk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/threkk"/>
    <language>en</language>
    <item>
      <title>How to have a Neovim configuration compatible with Vim</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Wed, 01 Dec 2021 18:31:15 +0000</pubDate>
      <link>https://dev.to/threkk/how-to-have-a-neovim-configuration-compatible-with-vim-2aln</link>
      <guid>https://dev.to/threkk/how-to-have-a-neovim-configuration-compatible-with-vim-2aln</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;So you can have your cake and eat it too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have been a &lt;a href="https://vim.org"&gt;Vim&lt;/a&gt; user for about 8 years already. Most of this time I have written code using &lt;a href="https://neovim.io"&gt;Neovim&lt;/a&gt;, and when they &lt;a href="https://neovim.io/roadmap/"&gt;announced&lt;/a&gt; the Lua integration, I was excited about the possibilities. I use my Vim configuration at home but also at work. In &lt;a href="https://booking.com"&gt;Booking.com&lt;/a&gt;, we do a reasonable amount of development in remote machines. Typically, you use ssh to remotely access a machine and do your work there. Many of those machines are quite liberal in regards of installing external packages (which includes Neovim), but other are heavily locked. However, we have an internal system that allows you to copy your dot files when you connect to a remote machine.&lt;/p&gt;

&lt;p&gt;For most of these years, I have kept my configuration compatible between Vim and Neovim. Every Vim configuration should work on Neovim by default, but the other way around. I managed to keep the especial Neovim features and plug-ins under wards so if needed I could launch the configuration in Vim if Neovim wasn’t available in the environment. This solution will not work anymore when with Lua plug-ins are involved.&lt;/p&gt;

&lt;h3&gt;
  
  
  The requirements
&lt;/h3&gt;

&lt;p&gt;These are the &lt;strong&gt;MUST have&lt;/strong&gt; for the configuration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It must work in Neovim and Vim with similar functionalities so it does not break my muscle memory.&lt;/li&gt;
&lt;li&gt;It must be a single configuration that works out of the box. If not, there will be two different configurations &lt;em&gt;de facto&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Neovim can use Lua and external software (for example, language servers or tools like eslint) without limitations. It will be running in my local machine or in a non critical server.&lt;/li&gt;
&lt;li&gt;Vim can &lt;strong&gt;only&lt;/strong&gt; use Vimscript. It can use plug-ins as far as they are written exclusively in Vimscript and can be tracked on git. This will run on restricted servers that only allow to copy configuration files.&lt;/li&gt;
&lt;li&gt;Minimise dependencies but keep it fast (Lua plug-ins &amp;gt; Vim plug-ins &amp;gt; external tools).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_opXGIkL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAjmQnC-0nwFXr3Bz6NaqdQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_opXGIkL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAjmQnC-0nwFXr3Bz6NaqdQ.png" alt="Output of the command tree -L 2 -I plugged on $HOME/.config/nvim" width="880" height="547"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How my Neovim configuration directory looks like.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is how my (Neo)vim configuration looks like. The directory lives in $HOME/.config/nvim, which is the default location for Neovim. When I need to use Vim, I set two symbolic links: &lt;code&gt;$HOME/.config/nvim&lt;/code&gt; → &lt;code&gt;$HOME/.vim&lt;/code&gt; and &lt;code&gt;$HOME/.config/nvim/init.vim&lt;/code&gt; → &lt;code&gt;$HOME/.vimrc&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;init.vim&lt;/strong&gt; : It is the entry point of the configuration. It loads the plug-ins using vim-plug, which will work for both. It also defined where the plug-ins should be located and which plug-ins to load depending on if it is Neovim or Vim. Additionally, it loads all the other configuration files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;common.vim&lt;/strong&gt; : It contains the common configuration like some of the bindings, tabs, word wrapping, etc. All these configurations are classical vim configurations and are the same for both. The rule of thumbs is that anything that is valid for both and not a plug-in goes here. If there are inconsistencies between platforms, the Neovim versions takes priority.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plugins.vim:&lt;/strong&gt; The complementary of &lt;strong&gt;common.vim&lt;/strong&gt;. Every plug-in configuration used in both versions goes here for instance, like &lt;a href="https://github.com/preservim/nerdtree"&gt;NERDTree&lt;/a&gt;, &lt;a href="https://github.com/easymotion/vim-easymotion"&gt;easymotion&lt;/a&gt; or &lt;a href="https://github.com/itchyny/lightline.vim"&gt;lightline.vim&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;only_vim.vim&lt;/strong&gt; : Self explanatory. These are the configurations that should be loaded only in Vim. They are mostly inconsistencies between platforms that require extra configuration or Vim only plug-ins. Because it is loaded after, it will overwrite Neovim’s configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;languages&lt;/strong&gt; : This directory contains custom languages configurations used by both versions, with one file per language and one additional file as a kitchen sink. For instance, the file &lt;code&gt;languages/golang.vim&lt;/code&gt; changes the configuration of the tab to use tabs instead of spaces when editing a &lt;code&gt;\*.go&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lua&lt;/strong&gt; : Contains all the Lua code for Neovim. It is a requirement of Neovim to place the Lua code here. Neovim configuration takes place and precedence in the common files, which means that this folder mostly contains the configuration of the Lua plug-ins. Every file is the configuration for a concrete plug-in, plus &lt;strong&gt;other.lua&lt;/strong&gt; as a kitchen sink. These plug-ins typically require heavy configuration because they set up language servers bindings, syntax highlight, autocomplete, etc. There is an additional folder, languages, which adds additional information required by the plug-ins that can be split by language. Most of the content is the configuration of the different language servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NYHLzsRK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0kzCacM0rIE_KkrzvfKY3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NYHLzsRK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0kzCacM0rIE_KkrzvfKY3w.png" alt="The last lines in the init.vim" width="880" height="818"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The order of loading the plug-ins in init.vim matter&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Some cool plug-ins that I use and their equivalences
&lt;/h3&gt;

&lt;p&gt;This is a bit off-topic, but this is a selection of some of the plug-ins I use and their equivalences between Vim and Neovim. For the full list of all the plug-ins in my configurations, you can check the init.vimfile &lt;a href="https://github.com/threkk/dotfiles/blob/master/dotfiles/config/nvim/init.vim"&gt;on Github&lt;/a&gt;. Remember that you can always use the Vim plug-ins in Neovim, but not the other way around.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/lewis6991/gitsigns.nvim"&gt;gitsigns.nvim&lt;/a&gt; → &lt;a href="https://github.com/airblade/vim-gitgutter"&gt;vim-gitgutter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvim-telescope/telescope.nvim"&gt;telescope.nvim&lt;/a&gt; → &lt;a href="https://github.com/ctrlpvim/ctrlp.vim"&gt;ctrlp.vim&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvim-treesitter/nvim-treesitter"&gt;nvim-treesitter&lt;/a&gt; → &lt;a href="https://github.com/sheerun/vim-polyglot"&gt;vim-polyglot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lukas-reineke/indent-blankline.nvim"&gt;indent-blankline&lt;/a&gt; → &lt;a href="https://github.com/tweekmonster/braceless.vim"&gt;braceless.vim&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Extra tricks
&lt;/h4&gt;

&lt;p&gt;This snippet will help you to load plug-ins conditionally using vim-plug.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" Lazy loading
" From [https://github.com/junegunn/vim-plug/wiki/faq#conditional](https://github.com/junegunn/vim-plug/wiki/faq#conditional-)-
" activation                            
function! Cond(cond, ...)
    let opts = get(a:000, 0, {})     
    return a:cond ? opts : extend(opts, { 'on': [], 'for': [] }) endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two variables can be used for distinguishing between Vim and Neovim. Technically you only need one, but it is more descriptive to have both. Defining the base path also helps as &lt;a href="https://github.com/junegunn/vim-plug"&gt;vim-plug&lt;/a&gt; needs to be able to find them in the right place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let is_vim = !has('nvim')
let is_nvim = has('nvim')

if is_nvim
    let $BASE = stdpath('config')  
else     
  let $BASE = '$HOME/.vim'                             
endif

call plug#begin($BASE.'/plugged')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Did you like this post? Let me know on &lt;a href="https://twitter.com/threkk"&gt;Twitter&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vim</category>
      <category>coding</category>
      <category>lua</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to use bookmarks in bash/zsh</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Sat, 04 Sep 2021 12:19:19 +0000</pubDate>
      <link>https://dev.to/threkk/how-to-use-bookmarks-in-bash-zsh-57a7</link>
      <guid>https://dev.to/threkk/how-to-use-bookmarks-in-bash-zsh-57a7</guid>
      <description>&lt;p&gt;Moving around your terminal effectively is going to make you more productive. Sometimes you need to quickly move between different projects or directories located in different places in your machine. For instance, maybe your code lives in ~/project/my-project, but the configuration of the server is in /etc/... Remembering locations is inefficient, and often they take longer to write. What if there is an easy, inexpensive solution in 4 lines of bash?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARfH4nMBm-1t-LISIRSvHXA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARfH4nMBm-1t-LISIRSvHXA.gif" alt="Example of how the autocomplete works with the proposed bookmarks."&gt;&lt;/a&gt;How my bookmarks look like&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install
&lt;/h3&gt;

&lt;p&gt;Here is where the magic is. Add these 4 lines of code to your bashrc or zshrc file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F974%2F1%2AsqJOhh_EJeLhxy8krAUTDw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F974%2F1%2AsqJOhh_EJeLhxy8krAUTDw.png" alt="if [-d “$HOME/.bookmarks”]; then export CDPATH=”.:$HOME/.bookmarks:/” alias goto=”cd -P” fi"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [-d "$HOME/.bookmarks"]; then
    export CDPATH=".:$HOME/.bookmarks:/"
    alias goto="cd -P"
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, you need to create the directory in your home folder or wherever it suits you, just remember to update the CDPATH variable above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/.bookmarks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to use
&lt;/h3&gt;

&lt;p&gt;To add a new bookmark, you just need to create a symbolic link to the folder in your bookmarks directory. I suggest you start all the bookmarks with the same character. This way, the autocomplete will suggest to you all the bookmarks available once you type the character. In my case, I chose the symbol @ . If you want to edit or remove the bookmark, delete the symbolic link and/or create a new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s path/to/certain/directory/with/my/project @important-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;The magic here is in the $CDPATH variable. $CDPATH is &lt;em&gt;a colon-separated list of directories used as a search path for the cd built-in command&lt;/em&gt;. It behaves like the $PATH when resolving binaries. The $CDPATH we define first attempts to locate the directories in the current directory, then in our bookmark’s directory, and finally in the root. Because we are using always the same starting character, if we type it, it will suggest all the bookmarks we have defined.&lt;/p&gt;

&lt;p&gt;Additionally, we also declare an alias for cd named goto. The option -P will resolve the symbolic links moving us to the directory instead of the symbolic link.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>zsh</category>
      <category>programming</category>
      <category>bash</category>
    </item>
    <item>
      <title>WTF is “0 but true”</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Fri, 07 May 2021 06:59:26 +0000</pubDate>
      <link>https://dev.to/threkk/wtf-is-0-but-true-mnf</link>
      <guid>https://dev.to/threkk/wtf-is-0-but-true-mnf</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F688%2F1%2AFV9v60pMmsTplVExUKtiqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F688%2F1%2AFV9v60pMmsTplVExUKtiqw.png" alt="Perl variable declaration of a string with the value “0 but true”."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have spent most of my life coding with JavaScript. For me, it is natural to use, and I know by heart most of its quirks and oddities. I understand many of these are quite strange for newcomers and can &lt;a href="https://javascriptwtf.com/" rel="noopener noreferrer"&gt;generate some aversion&lt;/a&gt;. However, recently learnt about one of these things in Perl that makes JavaScript oddities look amateurish.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perl? What is that?
&lt;/h3&gt;

&lt;p&gt;Perl is a scripting programming language that was quite popular in the early ’90s and lately has fallen in usage, although at the moment of writing it is still in the top 20 in the &lt;a href="https://www.tiobe.com/tiobe-index/" rel="noopener noreferrer"&gt;TIOBE index&lt;/a&gt;. It is still widely used in bioinformatics, sysops and projects like git or the Linux kernel among &lt;a href="https://en.wikipedia.org/wiki/Perl#Applications" rel="noopener noreferrer"&gt;many others&lt;/a&gt;. Perl is well known for its concise although often cryptic syntax and powerful one-liners and regular expressions. This is also its curse as it has been accused of being hard to maintain and &lt;a href="https://en.wikipedia.org/wiki/Perl#Criticism" rel="noopener noreferrer"&gt;“write-only”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Perl shares many similarities with languages like Python, JavaScript or PHP. Its variables may have different types, each one of them prefixes the variables names with a different sigil, similar to PHP: $scalar and list, which may be &lt;a class="mentioned-user" href="https://dev.to/array"&gt;@array&lt;/a&gt; or %hash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Perl
&lt;/h3&gt;

&lt;p&gt;The scalar represents a single value, that can be a string, a number, a float, or a reference to a list. We will not get deep into this, but the important idea is that Perl will transform between these different values depending on its needs as other scripting languages do. However, this sometimes is not explicit and it will complain if you use the wrong operator with the wrong type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0&amp;gt; my $aString = "string"
$res[1] = "string"
1&amp;gt; $aString == "string" ? "true" : "false";
Argument "string" isn't numeric in numeric eq (==) at reply input line 1.
Argument "string" isn't numeric in numeric eq (==) at reply input line 1.
$res[2] = "true"
3&amp;gt; $aString eq "string" ? "true" : "false";
$res[3] = "true"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we can see that Perl complained because we used a numeric operator instead of a string operator. Typically, we would execute the script in strict mode without warnings, which will give an error and stop execution.&lt;/p&gt;

&lt;p&gt;Perl does not have a boolean type, but different values will be evaluated as “true” or “false”. Quoting the official &lt;a href="https://perldoc.perl.org/perlsyn#Truth-and-Falsehood" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The number 0, the strings ‘0’ and “”, the empty list (), and undef are all false in a boolean context. All other values are true. Negation of a true value by ! or not returns a special false value. When evaluated as a string it is treated as “”, but as a number, it is treated as 0.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is special about "0 but true"
&lt;/h3&gt;

&lt;p&gt;"0 but true" :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a  &lt;strong&gt;string&lt;/strong&gt; …&lt;/li&gt;
&lt;li&gt;that can be used as  &lt;strong&gt;0&lt;/strong&gt; …&lt;/li&gt;
&lt;li&gt;but evaluates as  &lt;strong&gt;true&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we can operate with it like any other string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0&amp;gt; my $zeroButTrue = "0 but true";
$res[1] = "0 but true"
1&amp;gt; split " ", $zeroButTrue;
$res[2] = (0, "but", "true")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but we can also do some maths!! This will not work with other strings if we have strict mode and warnings enabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2&amp;gt; 10 + $zeroButTrue;
$res[3] = 10
3&amp;gt; my $oneString = "1 string";
$res[4] = "1 string"
4&amp;gt; 10 + $oneString;
Argument "1 string" isn't numeric in addition (+) at reply input line 1.
$res[5] = 11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we can see as well that this is not how 0 behaves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5&amp;gt; $zeroButTrue ? "true" : "false";
$res[6] = "true"
6&amp;gt; 0 ? "true" : "false";
$res[7] = "false"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  But why?
&lt;/h3&gt;

&lt;p&gt;The reason behind this odd behaviour is the way *nix systems handle process returns. In these systems, when a process returns 0, it means success or true, the opposite as in Perl or almost any other programming language. Any other number different from 0 is an error, being the value of the output of the error code. Taking these values without processing will create output. Therefore, instead of returning 0, it will return 0 but true and if it is an error, it will return the error code as a value. Error codes are still evaluated as a number, hence they will evaluate as true.&lt;/p&gt;

&lt;p&gt;This magic string is indeed a curiosity, and this could have been fixed by simply inverting the result of the return when evaluating (or using unless instead of if), also making the errors evaluate to false. There could be other design decisions for this choice that I am not aware of, but at the same time, it is a fun oddity that will always surprise beginners without being likely to harm them by chance.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://perldoc.perl.org/perlsyn#Truth-and-Falsehood" rel="noopener noreferrer"&gt;perlsyn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://perldoc.perl.org/functions/ioctl" rel="noopener noreferrer"&gt;ioctl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>wtf</category>
      <category>javascript</category>
      <category>softwareengineering</category>
      <category>perl</category>
    </item>
    <item>
      <title>TC39 proposal: Record and Tuples, the real immutable data structures in JavaScript.</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Mon, 26 Apr 2021 11:56:40 +0000</pubDate>
      <link>https://dev.to/threkk/tc39-proposal-record-and-tuples-the-real-immutable-data-structures-in-javascript-5d4d</link>
      <guid>https://dev.to/threkk/tc39-proposal-record-and-tuples-the-real-immutable-data-structures-in-javascript-5d4d</guid>
      <description>&lt;p&gt;&lt;a href="https://threkk.medium.com/tc39-proposal-record-and-tuples-the-real-immutable-data-structures-in-javascript-379e6b3089de?source=rss-1b85bdc283a2------2"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ax8WFntR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/756/1%2ABqL1KyRs3tp5G8ski8i6AQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was originally published in &lt;a href="https://threkk.medium.com/tc39-proposal-record-and-tuples-the-real-immutable-data-structures-in-javascript-379e6b3089de"&gt;Medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Records and tuplesOne of the misleading use cases for beginners in JavaScript is to create constant arrays and objects. With the introductions of ES6, we got two new declarators: &lt;code&gt;let&lt;/code&gt;, for mutable variables, and &lt;code&gt;const&lt;/code&gt;, for constants. Many beginners believe that this will make their objects and array immutable, to discover later that they are not. The object or array itself is immutable, but not their content. So far, we have relied on the method &lt;code&gt;Object.freeze&lt;/code&gt; to deal with this use case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is supposed to be immutable, isn't it?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wtf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Assertion failed: wtf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Introducing Record and Tuples.
&lt;/h1&gt;

&lt;p&gt;Records are immutable arrays. Tuples are immutable objects. &lt;strong&gt;They are compatible with Object and Array methods.&lt;/strong&gt; Essentially, you can drop a Tuple or a Record in any method that takes an object, or an array and it will behave as expected, unless this implies to modify the element. This applies to method of the standard library, iterators, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Record&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Tuple&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;// We can use most of the methods that work with Arrays and Objects.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK, it will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Although they will return tuples and records.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK, it will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Iterators work too&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="c1"&gt;// And you can nest them!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nested&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Nope&lt;/span&gt;
&lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// TypeError: Callback to Tuple.prototype.map may only return primitives, Records or Tuples&lt;/span&gt;

&lt;span class="c1"&gt;// This is ok&lt;/span&gt;
&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  However, with great power comes great responsibility.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The power
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Comparison by value:&lt;/strong&gt; Like other simple primitive types, they are compared by value, not by identity. Objects and arrays are equal if they are the same entity. Tuples and records are equal if they contain the same elements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;objA&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objA&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;objB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Same content, but different entities, false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objA&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;objC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;They are the say, it will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recordA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recordB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recordC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recordA&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recordA&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;recordB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK, will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recordA&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;recordC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK, will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You can convert to objects and array and the other way around:&lt;/strong&gt; Using the functions &lt;code&gt;Record()&lt;/code&gt; and &lt;code&gt;Tuple.from()&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Record&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They are identified as distinct types:&lt;/strong&gt; Using the operator typeof returns unique names for each of them.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;this will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tuple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;this will not print&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The responsibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;They can only contain primitive types:&lt;/strong&gt; They can only contain &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, &lt;code&gt;Symbol&lt;/code&gt;, &lt;code&gt;BigInt&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;Record&lt;/code&gt; and &lt;code&gt;Tuple&lt;/code&gt;. This is, no functions, objects, arrays, classes, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You can use them in Maps and Sets, but not with WeakMaps and WeakSets:&lt;/strong&gt; Quoting from the spec&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It is possible to use a Record or Tuple as a key in a Map, and as a value in a Set. When using a Record or Tuple here, they are compared by value.&lt;br&gt;
It is not possible to use a Record or Tuple as a key in a WeakMap or as a value in a WeakSet, because Records and Tuples are not Objects, and their lifetime is not observable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;JSON.stringify&lt;/code&gt; will work as expected, but &lt;code&gt;JSON.parse&lt;/code&gt; will still return objects and arrays:&lt;/strong&gt; There is a proposal to add &lt;code&gt;JSON.parseImmutable&lt;/code&gt; which will behave like &lt;code&gt;JSON.parse&lt;/code&gt; but returning records and tuples instead of arrays and objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This addition is welcomed as it has been a struggle to define immutable values in JavaScript, and confusing for many beginners. Prior solutions implied using external libraries like &lt;a href="https://immutable-js.github.io/immutable-js/"&gt;Immutable.js&lt;/a&gt;, workarounds in the standard library like &lt;code&gt;Object.freeze&lt;/code&gt; or conventions to achieve similar results.&lt;/p&gt;

&lt;p&gt;The proposal is currently on stage 2, so it is subject to changes. However, it already looks solid and I personally hope it makes it through and becomes a standard.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Proposal spec [&lt;a href="https://github.com/tc39/proposal-record-tuple"&gt;github&lt;/a&gt;, &lt;a href="https://tc39.es/proposal-record-tuple/"&gt;web&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://rickbutton.github.io/record-tuple-playground"&gt;Playground&lt;/a&gt; (beware, the current specification is not fully implemented)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tc39.es/proposal-record-tuple/tutorial/"&gt;Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tc39.es/proposal-record-tuple/cookbook/"&gt;Cookbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>immutable</category>
      <category>object</category>
      <category>tc39</category>
    </item>
    <item>
      <title>Go 2 generics in 5 minutes</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Fri, 05 Feb 2021 07:44:13 +0000</pubDate>
      <link>https://dev.to/threkk/go-2-generics-in-5-minutes-1fjf</link>
      <guid>https://dev.to/threkk/go-2-generics-in-5-minutes-1fjf</guid>
      <description>&lt;h3&gt;
  
  
  Go 2 generics in 5minutes
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2At1FT5haCFwcCvpOj" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2At1FT5haCFwcCvpOj" alt="Two generic gophers"&gt;&lt;/a&gt;Two generic gophers. Photo by &lt;a href="https://unsplash.com/@otohp_by_sakul?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Lukáš Vaňátko&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inclusion or not of generics in the Go language has been a long-standing discussion and cause of drama since the first appearance of the language in 2009. Rivers of ink have been poured in long discussions about if generics are good or bad, and if the language needs to support them or not. Up to this moment, the Go team has decided to leave generics outside the language.&lt;/p&gt;

&lt;p&gt;However, with the announcement of the second version of the language, the Go team opened the discussion to add generics to the language. There have been different drafts about how to add generics finally settling down in what it seems a final design draft.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generics in bullet points
&lt;/h3&gt;

&lt;p&gt;The draft is quite long but not as dense as it could have been expected for such a document. It is important to highlight that the objective of the Go team is to &lt;strong&gt;create a backwards compatible design which addresses people’s needs for generics without making the language more complex than necessary.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The specification can be summarised in the following bullet points, that we will develop after. However, it is advisable for anyone interested in the topic to read the full document linked at the bottom of the article. We are assuming that the reader is familiar with basic Go concepts like functions, types, and interfaces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions and types can have an additional type parameter list in front of the normal ones using square brackets to indicate the generic types used. These type parameters can be used like any other parameter in the rest of the definition and body.&lt;/li&gt;
&lt;li&gt;The type parameters are defined using constraints, that are interface types. Constraints define the methods required and types permitted for the type argument and describe the methods and operations available for the generic type.&lt;/li&gt;
&lt;li&gt;We can use type inference which will often permit omitting type arguments.&lt;/li&gt;
&lt;li&gt;We have a special constraint named any which behaves similarly to interface{}, and a new package named &lt;em&gt;constraints&lt;/em&gt; which will have commonly used constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Defining and using generic functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Functions can take an extra list of parameters surrounded by brackets instead of parenthesis, and they can be used as part of the definition and or the body&lt;/strong&gt;. These type parameters behave like normal parameters and they follow the same rules as the traditional parameter. These parameters will have an “interface” named constraint as a type, or the special interface any. Types can also have type parameters when defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// [https://go2goplay.golang.org/p/Z9e7O8ony21](https://go2goplay.golang.org/p/Z9e7O8ony21)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;

&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Functions’ type parameters can be used in the body of the function, and types using type parameters can be used in the module without restriction &lt;strong&gt;. The requirement to use them is to pass a type argument that fulfils the interface&lt;/strong&gt;. It is like assigning a variable of interface type: the type argument must implement the constraints of the type parameter, and the generic code can use only the operations permitted for the constraint or permitted for any type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// [https://go2goplay.golang.org/p/s8JCfu5qBKz](https://go2goplay.golang.org/p/s8JCfu5qBKz)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Hello "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: "Hello world"&lt;/span&gt;

&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Output: 123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defining constraints
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Constraints are interfaces.&lt;/strong&gt; You can expect the same features of interfaces on constraints, like embedding one constraint in other. Constraints have one addition to interfaces. Constraints may list explicitly types that may be used as type arguments by using the type keyword followed by a list of comma-separated types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// [https://go2goplay.golang.org/p/qWeRkYjjtKP](https://go2goplay.golang.org/p/qWeRkYjjtKP)&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SignedInteger&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constraints can be defined and exported as libraries, and the Go team stated that they would likely define and export a new standard library tentatively named constraints that would contain commonly used constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  The “any” constraint
&lt;/h3&gt;

&lt;p&gt;The any type is like the type interface{}. It is a constraint that whatever type can fulfil. However, it still has a few rules it needs to abide. Once you assign it a type to it, you need to keep using the same one. You can declare variables, pass, or return variables to other functions, take the addresses… but always the same type. You can convert or assign values of those types to the type interface{} and use type assertion to convert them back. You can also use the type as a case in a type switch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Vector is a name for a slice of any element type.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// T is []int&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;// func (v *Vector[int]) Push(x int) { *v append(*v, int) }&lt;/span&gt;
&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Output: [1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type inference in generics
&lt;/h3&gt;

&lt;p&gt;In many cases, we can use type inference to avoid having to explicitly write out some or all the type arguments. If you pass an argument to a function and other types depend on it, they can be inferred without explicitly saying it. It works in the same way as when you use a variable of a certain type as a parameter instead of a function which has an interface as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; 
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt;

&lt;span class="c"&gt;// Can be used in all these ways&lt;/span&gt;

&lt;span class="c"&gt;// Specify both type arguments explicitly. &lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="c"&gt;// Specify just the first type argument, for F, &lt;/span&gt;
&lt;span class="c"&gt;// and let T be inferred. &lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Don't specify any type arguments, and let both be inferred.&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part gets extremely messy extremely fast, so I cannot stop recommending to real the whole specification where this section is explained in deep detail. The important part to understand is that in many cases we will not need to specify all the type parameters explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclaimer and references
&lt;/h3&gt;

&lt;p&gt;This article is based on the following article, thread, and document. As it is a draft, it might change since the moment of publishing this article. To ensure corrected in all the examples, they have been extracted from the specification or from the Go 2 playground, where you can already head to if you want to test them by yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.golang.org/generics-proposal" rel="noopener noreferrer"&gt;Blog announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/golang/go/issues/43651" rel="noopener noreferrer"&gt;GitHub issue thread&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md" rel="noopener noreferrer"&gt;Go 2 type parameters draft&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://go2goplay.golang.org/" rel="noopener noreferrer"&gt;Go 2 playground&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This article was originally published &lt;a href="https://threkk.medium.com/go-2-generics-in-4-minutes-fa50dda91d7c" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>generics</category>
      <category>google</category>
      <category>go2</category>
    </item>
    <item>
      <title>Embedding files natively in Go 1.16</title>
      <dc:creator>Alberto de Murga</dc:creator>
      <pubDate>Fri, 25 Dec 2020 10:12:42 +0000</pubDate>
      <link>https://dev.to/threkk/embedding-files-natively-in-go-1-16-52h0</link>
      <guid>https://dev.to/threkk/embedding-files-natively-in-go-1-16-52h0</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--00fiU0HP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQrP3uWcGAZfNWFDCwZOdmQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--00fiU0HP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQrP3uWcGAZfNWFDCwZOdmQ.jpeg" alt=""&gt;&lt;/a&gt;&lt;a href="https://commons.wikimedia.org/wiki/File:Go_gopher_pencil_wrench.jpg"&gt;Gophers with a wrench&lt;/a&gt; by Renee French&lt;/p&gt;

&lt;p&gt;One of the most commonly noted upsides of Go is the compilation to a single binary. This makes deployments and dependency requirements easier to handle compared to other languages that require to install in the target system the individual dependencies which can potentially conflict with other software running or require to install duplicated packages.&lt;/p&gt;

&lt;p&gt;However, sometimes Go programs not always can be reduced to a single file. Assets like templates or images are not included as part of the binary and they need to manage and deployed independently. Although this has its benefits, like customising templates without having to recompile the whole program, it loses the benefits of a single unit when you do not want or do not expect to make a change in the assets, like with games.&lt;/p&gt;

&lt;p&gt;Traditionally, we have relied on third-party packages like &lt;a href="https://github.com/go-bindata/go-bindata"&gt;go-bindata&lt;/a&gt; or &lt;a href="https://github.com/rakyll/statik"&gt;statik&lt;/a&gt; to embed static assets in Go binaries. These tools essentially require to run a command against the assets we want to embed to create a Go file which contains a binary representation of them. Later, you import this generated file in your code and you access the files using some key based on the path or a virtual file system.&lt;/p&gt;

&lt;p&gt;These solutions have some issues in terms of development experience. They require an extra step to add/update assets every time they change and having the tool available in each environment in some concrete version. It is also an external dependency, which might be complicated to adopt in certain corporate environments. Also, to keep the component “go-getable”, you need to commit the generated files, which is not ideal either.&lt;/p&gt;

&lt;p&gt;In version 1.16 (not available yet as of December 2020), the Go team has introduced a &lt;a href="https://tip.golang.org/pkg/embed/"&gt;new package named&lt;/a&gt;&lt;a href="https://tip.golang.org/pkg/embed/"&gt;embed&lt;/a&gt; which solves these trade-offs by embedding the files during the building of the binary. Hence, we don't need to run additional commands before running go build or to track generated files. The go build system will recognise the directives and populate the variables with the matching files.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;h4&gt;
  
  
  General conditions
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;If any patterns are invalid or have invalid matches, the build will fail.&lt;/li&gt;
&lt;li&gt;The directive must immediately precede a line containing the declaration of a single variable. Only blank lines and comments are permitted between the directive and the declaration.&lt;/li&gt;
&lt;li&gt;Patterns must not contain . or .. path elements nor begin with a leading slash.&lt;/li&gt;
&lt;li&gt;To match everything in the current directory, use *.&lt;/li&gt;
&lt;li&gt;Patterns must not match files outside the package’s module, such as .git/ or symbolic links.&lt;/li&gt;
&lt;li&gt;Each pattern in a line must match at least one file or non-empty directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Embedding a file as a string
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The files are stored as string or []byte.&lt;/li&gt;
&lt;li&gt;You can use a single go:embed directive per variable.&lt;/li&gt;
&lt;li&gt;The directive must refer to a single file.&lt;/li&gt;
&lt;li&gt;You can use a blank import.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypackage&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;//go:embed README.md&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="c"&gt;//go:embed image.png&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; 

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Embedding several files as a file system.
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The files are stored as embed.FS&lt;/li&gt;
&lt;li&gt;embed.FS is read-only and safe to use from different goroutines concurrently.&lt;/li&gt;
&lt;li&gt;embed.FS implements fs.FS, so it can be used with any package that understands file system interfaces&lt;/li&gt;
&lt;li&gt;You can use a single or multiple go:embed declarations. Each declaration can refer to one or multiple paths separated by spaces.&lt;/li&gt;
&lt;li&gt;If a pattern names a directory, all files in the directory are embedded recursively, except that files with names beginning with . or _ .&lt;/li&gt;
&lt;li&gt;If you use * after the directory, it will add also files prefixed with . and _ .
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypackage&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"embed"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// It will add the specified files.&lt;/span&gt;
&lt;span class="c"&gt;//go:embed favicon.ico robots.txt index.html&lt;/span&gt;
&lt;span class="c"&gt;// It will add all non-hidden file in images, css, and js.&lt;/span&gt;
&lt;span class="c"&gt;//go:embed image/ css/ js/&lt;/span&gt;
&lt;span class="c"&gt;// It will add all the files in downloads, including hidden files.&lt;/span&gt;
&lt;span class="c"&gt;//go:embed downloads/*&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FS&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information, check the references below. Do you have any feedback? You can &lt;a href="https://twitter.com/threkk"&gt;reach me on Twitter&lt;/a&gt; or leave a comment below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tip.golang.org/pkg/embed/"&gt;https://tip.golang.org/pkg/embed/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/go-bindata/go-bindata"&gt;https://github.com/go-bindata/go-bindata/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rakyll/statik"&gt;https://github.com/rakyll/statik/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Changelog&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2020–02–01: As pointed in the Medium comments, the article had a typo in the code directives, which should not contain a space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This post was originally published at &lt;a href="https://threkk.medium.com/embedding-files-natively-in-go-1-16-2a2f2070617d"&gt;Medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>embed</category>
      <category>native</category>
      <category>files</category>
      <category>go</category>
    </item>
  </channel>
</rss>
