<?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: Gregory Witek</title>
    <description>The latest articles on DEV Community by Gregory Witek (@gregorywitek).</description>
    <link>https://dev.to/gregorywitek</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%2F440059%2F638f4378-f62c-4fc2-8078-73019fcc4769.jpg</url>
      <title>DEV Community: Gregory Witek</title>
      <link>https://dev.to/gregorywitek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gregorywitek"/>
    <language>en</language>
    <item>
      <title>From init.vim to init.lua  - a crash course</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Mon, 01 Nov 2021 21:21:12 +0000</pubDate>
      <link>https://dev.to/gregorywitek/from-initvim-to-initlua-a-crash-course-27lb</link>
      <guid>https://dev.to/gregorywitek/from-initvim-to-initlua-a-crash-course-27lb</guid>
      <description>&lt;p&gt;Earlier this year maintainers of Neovim have released version 0.5 which, among other features, allows developers to configure their editor using Lua instead of VimL. In this article I'll share a few basic rules on how to transition from one configuration to another. This is not a complete guide, but it covers almost 100% of what I needed in order to completely move away from init.vim to init.lua. In the bottom of the article you're also find a link to my config files so that you can look at them and copy if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lua in 1 minute
&lt;/h2&gt;

&lt;p&gt;First, it's good to spend 10-15 minutes learning Lua in order to easily write the new config. I used the &lt;a href="https://learnxinyminutes.com/docs/lua/"&gt;Learn X in Y minutes page&lt;/a&gt;, but I guess anything works. If you want to spend 1 minute instead, here you go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- this is a comment&lt;/span&gt;
&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt; &lt;span class="c1"&gt;-- this global variable represents a number&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;num2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="c1"&gt;-- local variable&lt;/span&gt;
&lt;span class="n"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'this is a string'&lt;/span&gt;
&lt;span class="n"&gt;str2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"and so is this"&lt;/span&gt;
&lt;span class="n"&gt;str3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;[[and this is a string too]]&lt;/span&gt;
&lt;span class="n"&gt;str4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"string "&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="s2"&gt;"concatenation"&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;-- booleans and logical operators&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'something'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"YES"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="n"&gt;str2&lt;/span&gt; &lt;span class="o"&gt;~=&lt;/span&gt; &lt;span class="s1"&gt;'is not equal'&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Maybe'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'no'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;printText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;tab1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'this'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'is, '&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="s1"&gt;' } -- aka array
-- tables are both arrays and dictionaries
tab2 = { also = '&lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="s1"&gt;' }
tab2["new_key"] = "new value"

print(tab2["also"])

require('&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="s1"&gt;') -- will find and execute plugins.lua file
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's of course way more than that, but for me this + copying some stuff from plugins documentation was enough to write my config files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Config basics
&lt;/h2&gt;

&lt;p&gt;Ok, now onto the config. In Vim we use a number of functions that are dedicated to the editor configuration (the whole language is dedicated to it, really). In Lua we're using a general programming language and we'll use an API to interact with Neovim configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vim.cmd("set notimeout")&lt;/code&gt; - this is a safety net, whatever string you pass as parameter to &lt;code&gt;vim.cmd&lt;/code&gt; will be interpreted as VimL. For multiple lines, wrap string in double brackets:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vim.cmd([[
set notimeout
set encoding=utf-8
]])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vim.g.mapleader = ","&lt;/code&gt; is equivalent of &lt;code&gt;let g:mapleader = ','&lt;/code&gt;; &lt;code&gt;vim.g&lt;/code&gt; is a table represeting global variables&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim.o.encoding="utf-8"&lt;/code&gt; is equivalent of &lt;code&gt;set encoding=utf-8&lt;/code&gt;; &lt;code&gt;vim.o&lt;/code&gt; is for global options, &lt;code&gt;vim.wo&lt;/code&gt; for window options and &lt;code&gt;vim.bo&lt;/code&gt; for buffer options&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim.fn&lt;/code&gt; is a table representing functions. You can refer to a function &lt;code&gt;thisIsMyFun&lt;/code&gt; using &lt;code&gt;vim.fn.thisIsMyFun&lt;/code&gt; or &lt;code&gt;vim.fn["thisIsMyFun"]&lt;/code&gt; and you can call it using &lt;code&gt;vim.fn.thisIsMyFun()&lt;/code&gt; or &lt;code&gt;vim.fn["thisIsMyFun"]()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim.api&lt;/code&gt; is a collection of API functions. I used only one: &lt;code&gt;vim.api.nvim_set_keymap&lt;/code&gt; that maps certain key combinations to some functions (more about it below)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Moving settings to Lua
&lt;/h2&gt;

&lt;p&gt;Moving most of the settings is pretty straightforward. You just replace &lt;code&gt;set x = y&lt;/code&gt; with &lt;code&gt;vim.o.x = "y"&lt;/code&gt;. There are however some catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pairs of boolean settings are merged into one setting, e.g. instead of &lt;code&gt;set wrap&lt;/code&gt; and &lt;code&gt;set nowrap&lt;/code&gt; you write &lt;code&gt;vim.o.wrap = true&lt;/code&gt; and &lt;code&gt;vim.o.wrap = false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;home directory problems - I had issue using &lt;code&gt;~&lt;/code&gt; as a reference to home directory for some backup files etc. so instead I set &lt;code&gt;HOME&lt;/code&gt; variable that I used by writing &lt;code&gt;HOME = os.getenv("HOME")&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;string concatenation uses &lt;code&gt;..&lt;/code&gt; operator, so to refer to my backup dir I wrote &lt;code&gt;vim.o.backupdir = HOME .. "/.vim/backup"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;double backslash - if you want to pass a special character &lt;code&gt;\t&lt;/code&gt; to Vim, you need to write it as &lt;code&gt;"\\t"&lt;/code&gt; in Lua&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mapping keys
&lt;/h2&gt;

&lt;p&gt;The Lua API has a function to map keys to some functions. The function signature is &lt;code&gt;vim.api.nvim_set_keymap(mode, keys, mapping, options)&lt;/code&gt;, where &lt;code&gt;mode&lt;/code&gt; refers to a letter representing editor mode ( &lt;code&gt;n&lt;/code&gt; for normal, &lt;code&gt;i&lt;/code&gt; for insert etc.) just like in original vim functions like &lt;code&gt;nmap&lt;/code&gt; or &lt;code&gt;imap&lt;/code&gt;, &lt;code&gt;keys&lt;/code&gt; is a string representing a combination of keys, &lt;code&gt;mapping&lt;/code&gt; is a string representing what the keys map to, and options are a table where you can pass some additional settings. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_set_keymap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;":Git blame&amp;lt;cr&amp;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;noremap&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is equivalent of &lt;code&gt;nnoremap &amp;lt;leader&amp;gt;a &amp;lt;cmd&amp;gt;Git blame&amp;lt;cr&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I didn't check what are all the options that can be passed in the 4th argument, 2 that I used are &lt;code&gt;noremap = true&lt;/code&gt; and &lt;code&gt;silent = true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I also wrote myself a few simple functions to avoid typing &lt;code&gt;vim.api...&lt;/code&gt; every time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_set_keymap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;noremap&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="n"&gt;silent&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="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;imap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'i'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shortcut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these functions my example above became just &lt;code&gt;nmap("&amp;lt;leader&amp;gt;a", "&amp;lt;cmd&amp;gt;Git blame&amp;lt;cr&amp;gt;")&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package manager
&lt;/h2&gt;

&lt;p&gt;It's very probable that you already use some package manager for Neovim, and when moving to Lua you don't need to change it, you can just wrap your whole plugin list in &lt;code&gt;vim.cmd&lt;/code&gt; and continue using it as before.&lt;/p&gt;

&lt;p&gt;I decided to try a new manager called &lt;a href="https://github.com/wbthomason/packer.nvim"&gt;Packer&lt;/a&gt;, which is written in Lua and requires Neovim 0.5. The installation was a bit troublesome, because I didn't know what &lt;code&gt;packpath&lt;/code&gt; is and that Packer requires some very specific names of the directories to find packages. Anyway, I moved it to &lt;code&gt;~/.config/nvim/pack/packer/start/packer.nvim&lt;/code&gt; directory and it worked nicely (though I'm sure there's a better way to install it).&lt;/p&gt;

&lt;p&gt;Besides the installation, Packer is both easy to use and has all the features I need (and a lot that I don't need). The basic config example looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'packer'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="s1"&gt;'wbthomason/packer.nvim'&lt;/span&gt;

  &lt;span class="c1"&gt;-- common&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="s1"&gt;'tpope/vim-fugitive'&lt;/span&gt; &lt;span class="c1"&gt;-- Git commands&lt;/span&gt;
  &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'tpope/vim-rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ruby"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;-- only load when opening Ruby file&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need some more advanced functionality, I recommend checking the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other plugins
&lt;/h2&gt;

&lt;p&gt;There is a number of other plugins that are available for Neovim 0.5 and I found myself replacing some of plugins I had used before with the new alternatives. I won't cover them here (maybe in another post), but here are a few that you can check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nvim-lspconfig&lt;/code&gt; together with &lt;code&gt;nvim-lspinstall&lt;/code&gt; and &lt;code&gt;lspsaga.nvim&lt;/code&gt; use the new, built-in LSP in Neovim and provide some useful functions. Together they allow me to easily install and use language servers (e.g. to display function documentation or jump to a definition). Together with &lt;code&gt;nvim-compe&lt;/code&gt; (autocompletion) I use them to replace &lt;code&gt;Ale&lt;/code&gt; and &lt;code&gt;coc.vim&lt;/code&gt;, &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;telescope.nvim&lt;/code&gt; replaces any search plugin you use ( &lt;code&gt;ctrl-p&lt;/code&gt;, &lt;code&gt;fzf.vim&lt;/code&gt; etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gitsigns&lt;/code&gt; replaces &lt;code&gt;vim-gitgutter&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a few more like &lt;code&gt;lualine.vim&lt;/code&gt; that can replace &lt;code&gt;powerline&lt;/code&gt; or &lt;code&gt;airline&lt;/code&gt;, but I'm yet to try it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The whole process of moving 350 lines of &lt;code&gt;init.vim&lt;/code&gt; to &lt;code&gt;init.lua&lt;/code&gt; took me around 2h, including time to organize the files (Lua allows you to use multiple config files, see my example below) and excluding time to play with new plugins. I spent around 1 hour moving 90-95% of the content, and another hour solving some issues like home directory or some broken config. In the end I found the whole process rather quick and definitely rewarding, though I'm sure a lot of things can be done better. If you plan to use new capabilities of Neovim 0.5 I definitely recommend moving your config to Lua.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My config in VimL and Lua:&lt;/strong&gt; &lt;a href="https://github.com/arnvald/viml-to-lua"&gt;https://github.com/arnvald/viml-to-lua&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vim</category>
    </item>
    <item>
      <title>Why nobody hires junior developers and what happens next</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 28 Sep 2021 20:55:56 +0000</pubDate>
      <link>https://dev.to/gregorywitek/why-nobody-hires-junior-developers-and-what-happens-next-dlm</link>
      <guid>https://dev.to/gregorywitek/why-nobody-hires-junior-developers-and-what-happens-next-dlm</guid>
      <description>&lt;p&gt;While the number of job opportunities for software developer skyrockets together with salaries all around the world, fresh grads and junior developers struggle to even get invited for the interviews. Why does it happen and can we do anything about it?&lt;/p&gt;

&lt;p&gt;Tech industry has still relatively low barrier of entry, especially when compared to other well-paying jobs (think 5+ years of school for lawyers and doctors). However looking at the number of entry-level job offers on LinkedIn or other job portals, it seems that the golden days for bootcamp graduates and self-taught devs are over. Finding job as a junior has already been challenging in the last 2 years, but 2021 seems like a real bad time to be searching for the first job in tech.&lt;/p&gt;

&lt;p&gt;In the last few years I've been heavily involved in hiring, I've worked with a number of recruiters, and I spent some collaborating with coding bootcamps. Based on my discussions adn observations, I believe there are 2 main reasons behind the current situation: tragedy of the commons and COVID-19. The first one has been a problem for years, the second one has amplified the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short-term gains, long-term loss
&lt;/h2&gt;

&lt;p&gt;Imagine a following situation: a group of fishermen have access to a lake with fish. The lake does not belong to any particular person, and all fishermen go there daily and catch a few fish to feed their families and sell to fellow townmen. That situation lasts for years and remains stable. Then one day one of the fishermen figures out that he can catch more fish and sell them also in other towns.&lt;/p&gt;

&lt;p&gt;Soon other fishermen copy that model and everyone happily catches a lot of fish and makes more money. Until one day the fishermen notice that it takes them more and more time to catch fish, until one day they come home empty handed. The fishermen never considered that they need to maintain the population of fish in the lake, and because of their greed they caught all fish and left the lake empty.&lt;/p&gt;

&lt;p&gt;This kind of situation has a name - &lt;a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons"&gt;the tragedy of the commons&lt;/a&gt; - and you can think about it as a &lt;a href="https://dev.tothe%20tragedy%20of%20the%20commons"&gt;multiplayer prisoner's dilemma&lt;/a&gt;. The dilemma is simple - you can choose to cooperate with others (limit number of fish you catch with sustainability in mind) or betray them (catch more fish for higher short-term gains). However if enough people betrays others, eventually they deplete the resource they use and everyone loses.&lt;/p&gt;

&lt;p&gt;Tragedy of the commons is not just a thought experiment. It happens in real life, too. A fairly recent case comes from Thailand and its famous Maya bay,  featured movie "The Beach" with Leonardo di Caprio. Maya bay is a gorgeous spot located at one of the Phi Phi islands that every day used to draw thousands of tourists. Unfortunately the trip organizers were too greedy and the fragile ecosystem of the bay could not handle the number of boats and people, and the amount of trash left there. In 2018 the government of Thailand decided to close the island for recovery, and as of September 2021 it remains unavailable for tourists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OwezRnZG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/IMG_3892.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OwezRnZG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/IMG_3892.JPG" alt="Why nobody hires junior developers and what happens next"&gt;&lt;/a&gt;A photo I took in Maya bay back in 2017, while it was still open (though the damage was already very visible)&lt;/p&gt;

&lt;h2&gt;
  
  
  Too many betrayals among tech companies
&lt;/h2&gt;

&lt;p&gt;What does all this have to do with hiring in tech? We're dealing with a similar kind of a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;everyone wants to have senior developers, because they provide value&lt;/li&gt;
&lt;li&gt;in order to have a senior developer, we need a junior dev + a lot of time + proper training&lt;/li&gt;
&lt;li&gt;in order to train junior developers, company needs to invest: senior developers spend less time on product (sacrifice immediate profit) so that they can support others (with long-term gain in mind)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the twist - a company might invest in a developer, but not profit from them, because once that developer gains enough experience and skills to provide value, they'll start getting other job offers, and as we know changing jobs brings higher raise than staying.&lt;/p&gt;

&lt;p&gt;Knowing all that, companies can take different strategy depending on their circumstances:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;top companies (big tech, high growth startups) figure out that they don't really need to hire a lot of junior developers, they'll just hire the best seniors from other companies by offering them way higher compensation&lt;/li&gt;
&lt;li&gt;above average companies (other highly profitable enterprises) figure out they don't need to hire that many junior developers either, they'll just hire senior or mid-level devs who can't get a job at top companies&lt;/li&gt;
&lt;li&gt;the remaining companies know they are at the bottom of the food chain - they train developers that later find better paying options. These companies still hire juniors, because they don't have much choice, but their hiring becomes limited because there are not enough experienced devs for mentoring&lt;/li&gt;
&lt;li&gt;software houses are a bit of a special case - since they charge per person per day, even less experienced developers quickly become profitable for the company. It's tough to convince customers to add junior dev to the team, but often software houses just promote people very quickly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P2WvTQGn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/Shared-resource-1-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P2WvTQGn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/Shared-resource-1-.png" alt="Why nobody hires junior developers and what happens next"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We end up in a situation where the demand for senior developers far outweighs the capacity and willingness of the companies to train juniors. Up until recently it wasn't that bad though, we were in kind of an stable situation - the number of developers needed was growing steadily, the attrition was stable, companies were offering some internships and entry-level positions, universities and bootcamps provided streams of candidates. It wasn't very easy to get the first job in the industry, but with enough effort and determination it was possible even for someone who has just started programming.&lt;/p&gt;

&lt;p&gt;And then came the pandemic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody hires juniors anymore
&lt;/h2&gt;

&lt;p&gt;After the initial shock of the pandemic, all the hiring freezes and layoffs, companies figured out where they stand and started hiring again. The bounce was strengthened by sudden spike in demand for digital services (retailers moving to on-line, booming businesses like virtual events and all kinds of deliveries), influx of cash from investors, and the need to catch-up after the hiring freeze.&lt;/p&gt;

&lt;p&gt;Together with a lot of burnout cases and people taking longer leaves, it created a spike in need for experienced engineers, and made almost no impact (or maybe even a negative impact) on a number of entry-level roles. With all the pandemic-related challenges and opportunities, investing in junior developers is not an urgent matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote work
&lt;/h3&gt;

&lt;p&gt;Working from home comes with a lot of benefits, but also plenty of challenges - how to keep the communication effective? How to ensure people keep the healthy balance between work and time off? How do we make remote teams work effectively? How do we balance between seeing each others faces while avoiding the fatigue related to constantly being on the camera?&lt;/p&gt;

&lt;p&gt;We all still struggle with that, but  then comes another problem - how do we onboard new people? We need to deliver them the equipment, make sure they have all their need for their home office, but more importantly, we need to figure out how to share the knowledge and feel people excited about joining the company. There's no onboarding day anymore, we can't gather all new joiners in one room anymore to let them meet each other and to have a big welcome breakfast.&lt;/p&gt;

&lt;p&gt;And then comes another complication - what if these people are fresh grads? How can we hire people for their first job while we struggle with onboarding in general? The answer is - let's put that on hold and figure it out later. Junior roles are traditionally the easiest to fill, so we can just stop for a few months and hire them later, when we are ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HwKNZfL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/pandemic-junior-reasons.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HwKNZfL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/09/pandemic-junior-reasons.png" alt="Why nobody hires junior developers and what happens next"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Everyone's understaffed
&lt;/h3&gt;

&lt;p&gt;The 2nd effect of the pandemic is that everyone urgently needs senior developers. Gergely Orosz wrote a &lt;a href="https://blog.pragmaticengineer.com/advice-for-tech-workers-to-navigate-a-heated-job-market/"&gt;great blog post about it&lt;/a&gt;, where he explains in detail why there's a shortage of senior developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sudden demand for digital products and services means companies need to scale and, in order to remain competitive, keep innovating, so they need experienced devs&lt;/li&gt;
&lt;li&gt;demand for developers (and limited supply) means companies have to pay more and offer more benefits&lt;/li&gt;
&lt;li&gt;that means it's a good time to change jobs - new job usually means a nice raise, but this time instead of 20% it can be even 50-70%&lt;/li&gt;
&lt;li&gt;that creates a lot of movement in the market, on one hand companies lose people, on the other bring a lot of new devs, so they need to spend a lot of time onboarding (which also puts pressure on remaining employees!)&lt;/li&gt;
&lt;li&gt;on the other hand people are exhausted because of the pandemic and want to take longer break; with the huge demand for developers they feel more comfortable taking a few months off (so supply is even smaller)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once again, this affects junior developers in a negative way. Since everyone desperately needs senior devs, nobody wants to put even more pressure on their devs to help onboard and train junior devs.&lt;/p&gt;

&lt;p&gt;And because a lot of tech companies have been playing defectors for the last few years and didn't invest enough in junior developers when they could, now everyone struggles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The way forward
&lt;/h2&gt;

&lt;p&gt;The question remains - what now? Sooner or later the situation will become more stable, but is there anything we can do to help each other? None of us alone will make a big difference, but we still can help to bring a little bit of balance in the industry, and everyone can contribute.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should you care?
&lt;/h3&gt;

&lt;p&gt;One thing that you might be asking yourself is "why do I care?". If you're a senior developer, you technically benefit from the current situation - you can easily jump jobs and get a significant raise every time. But even then, lack of junior developers has a negative impact on your career - when there are no junior developers, there are no people to teach, so you can't improve as a mentor. There are no people who can take easier tasks, so you have to do them. Finally, the teams can't grow as fast as they could, so even if you could get promoted to lead your own team, your company only hires senior devs, and it's hard to find them.&lt;br&gt;
And if you're a lead dev or a manager, you should care about building a stable situation where more experienced developers can make a bigger impact by supporting junior devs and focusing on tasks that only they can do. Without junior developers, that balance is gone.&lt;/p&gt;
&lt;h3&gt;
  
  
  As a junior dev looking for work
&lt;/h3&gt;

&lt;p&gt;If you're currently looking for your first job in the tech industry, there are 2 things that you should do: expand your search and make it sustainable.&lt;/p&gt;

&lt;p&gt;Expand: reach out to companies directly. Smaller companies could offer you a position even if they are not actively looking for junior candidates. Attend events - there are a lot of virtual, free meetups where you can chat with people. Go beyond the stack that you know, if you know React check also positions for Vue or  Angular developers.&lt;/p&gt;

&lt;p&gt;Make it sustainable: it may take you even 12 months to find a job. Pace yourself, make a list of companies you want to write to and make it a habit to send a few applications a day. Take some days off, remember to relax, you are in it for the long term.&lt;/p&gt;

&lt;p&gt;A year ago I made 2 videos where I talked exactly about this topic. Check them out, each of them is 5-10 minutes:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kzG3SeKmGP0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/w-4P7nz0Fa8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  As an employed developer
&lt;/h3&gt;

&lt;p&gt;If your company doesn't hire junior developers at all, understand why, see whether it's a rule or just nobody thought of opening junior roles. Suggest to your managert that it would help to have someone less experienced, so that you can teach them but also delegate simpler tasks that don't need someone with your experience. If not junior devs - maybe interns? In my first job I started an internship program that provided a lot of benefits over the years. If you work for a small company, it should be much easier than in a corporation!&lt;/p&gt;

&lt;p&gt;If you are willing to help others in your free time, you can become a mentor or a coach - there are organizations out there who help people break into the industry. In the past I had a pleasure of working with a free, volunteer-based bootcamp. I helped someone to change their career, and while doing this I became a much better mentor than I used to be. It's a hard, but very rewarding work.&lt;/p&gt;

&lt;h3&gt;
  
  
  As a manager
&lt;/h3&gt;

&lt;p&gt;If you're an engineering manager, you have an impact on hiring - use it! If your team is doing well, ask your manager for additional headcount and make sure it's an entry-level position. Talk to your peer and discuss with them how you can benefit from having more junior devs (I'll write about the benefits another time, stay tuned!). It's not an easy thing to do, especially if your company has practiced the parasite "only seniors here" model until now, but you can always try.&lt;/p&gt;

&lt;h3&gt;
  
  
  As an executive
&lt;/h3&gt;

&lt;p&gt;If you're a VP of Engineering or CTO you are probably responsible for (or at least can influence) the hiring plans and strategy. Take junior positions into account - find a ratio that will work in your teams (1 junior in a team of 4 or 5, for example) and ensure that your company provides an inclusive, welcoming environment for people who have just started their career in software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to where we started?
&lt;/h2&gt;

&lt;p&gt;The current tech boom won't last forever. Eventually things will become more stable. The world will keep innovating, the demand for developers will remain, but it won't be that urgent. In a couple of months the bounce caused by the pandemic will weaken and we'll go back to where we were before - a system where juniors don't have it easy, but where it's possible for them to get interviews, and eventually start their career in software development.&lt;/p&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
      <category>community</category>
    </item>
    <item>
      <title>Why you should always negotiate salary and how to do it</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Mon, 30 Aug 2021 22:17:03 +0000</pubDate>
      <link>https://dev.to/gregorywitek/why-you-should-always-negotiate-salary-and-how-to-do-it-412p</link>
      <guid>https://dev.to/gregorywitek/why-you-should-always-negotiate-salary-and-how-to-do-it-412p</guid>
      <description>&lt;p&gt;Salary negotiation is a widely covered topic - there are many videos, articles, and even books about it. As software developers we are usually in advantageous position - our industry is booming and our skills are in demand, therefore we should easily be able to negotiate salaries. Despite this, a lot of people decide not to negotiate the offers they get, because they're afraid. In this article I explain why you should always negotiate the job offer using some basic concepts from probability and game theory. And in the end of the article you'll find my video where I explain how to start negotiation when you're afraid to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expected payoff
&lt;/h2&gt;

&lt;p&gt;Let's start with a concept of "expected payoff" (also known as "expected value") that I'll use throughout the whole article. Expected payoff is a single numeric value that represents what you should expect on average when participating in some activity where you have multiple options and you don't know which one is better. Using the probabilitis and values of possible outcomes, you can calculate the expected payoff of each option and choose the one that has a better potential.&lt;/p&gt;

&lt;p&gt;Let's say our friend offers us to play a game: we'll roll a 6-side dice, and if we roll 1 or 2, we pay our friend $10. If we get 3-4 we pay our friend $5, and if we get 5 or 6 our friend pays us $20. We can use expected payoff to see whether playing this game is a good idea or not. In order to do it, we multiply the value of each possible outcome by it's probability and then we add all the values together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there's 1/3 chance that we'll roll 1 or 2, and we'll pay $10, so we write it as 1/3*$-10 = $-3.33&lt;/li&gt;
&lt;li&gt;there's 1/3 chance we'll roll 3 or 4 and we'll lose $5: 1/3*$-5 = $-1.67&lt;/li&gt;
&lt;li&gt;there's 1/3 chance we'll roll 5 or 6 and we'll get $20: 1/3*20 = $6.67&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we add all the values together: $-3.33 + ($-1.67) + $6.67 = $1.67.&lt;/p&gt;

&lt;p&gt;The outcome tells us that if we play the game on average we will win $1.67 (and if we don't play, the value is 0), so we should agree to play it. Of course the question remains why our friend wants to play such game if they're expected to lose!&lt;/p&gt;

&lt;p&gt;On the contrary, gambling or lottery tickes have negative expected payoffs. If your chance to win $1 million is 1 in 5 million, and a single lottery ticket costs $2, then the expected payout is $-1.8. Of course people still buy those tickets hoping they'll end up millionaires, but technically it's better to invest that money in something else.&lt;/p&gt;

&lt;p&gt;This concept of expected payoff, enriched with more advanced ideas from game theory or decision theory (that help in more uncertain situations), can be applied in multiple areas of life. Should you buy a house or rent? Should you invest in a new company? Should you choose a startup job offer over a corporate one?&lt;/p&gt;

&lt;p&gt;Now let's have a look how it can help us understand that negotiating the job offer is a good idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fear of losing the offer
&lt;/h2&gt;

&lt;p&gt;One of the most common, if not the most common reason why people don't negotiate job offers is the fear that company will withdraw the offer. Candidates believe that if they ask for more, the company will decide that they don't want to have such employee. In order to understand why this makes very little sense to the company, let's use the expected payoff.&lt;/p&gt;

&lt;p&gt;It's very hard to put some specific value to the outcomes, hiring a candidate does not directly translate to a profit, so for now I'll use abstract units. Let's say the company made an offer of $100,000 and the candidate asks for $120,000 instead. The company can't increase the salary, and therefore they have 2 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rescind the offer&lt;/li&gt;
&lt;li&gt;tell candidate that they won't offer more, but leave the offer on the table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In terms of payoff, we can assign value 1 if the candidate joins the company, and 0 if they don't. The question is what should the company do.&lt;/p&gt;

&lt;p&gt;The 1st option means the candidate won't join for sure, so the expected payoff of that strategy is 0. The 2nd option has some uncertainty - the candidate will probably reject the offer, but there's some chance they'll accept it. If we assume that there's 10% chance that the candidate will still join the company, then the expected payoff is 10%*1 + 90%*0 = 0.1, if we believe it's 5%, the payoff is 5%*1 + 95%*0 = 0.05 . &lt;strong&gt;Even if the chance is just 1%, it's still better than withdrawing the offer!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course reality is more complex - maybe the company has just 1 seat and they have another, equally good candidate waiting for their answer, but even in such case it's better to keep the offer on the table and tell the first candidate that the company needs an answer in 1-2 days.&lt;/p&gt;

&lt;p&gt;Does it mean that offer withdrawal is a myth? No, it still happens, but the companies that do it either act irrationally, or they're looking for programmers that won't stand up for themselves, that will always blindly accept whatever the company offers. In other words - they're not good companies, and you're better off avoiding them.&lt;/p&gt;

&lt;h2&gt;
  
  
  To give more or not - company's perspective
&lt;/h2&gt;

&lt;p&gt;That was a trivial example (we'll use it later though!) so now let's move to a more complex topic - should the company offer candidates more money when candidates negotiate, or not?&lt;/p&gt;

&lt;p&gt;Let's imagine that we offer candidate $130,000 and the candidate asks for $120,000, so we can limit our options to following 3:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we don't offer anything more - in that case we pay candidate $130,000 and our potential payoff is 1, but the chance the candidate accepts the offer is only 40%&lt;/li&gt;
&lt;li&gt;we try to meet the candidate in the middle with an offer of $140,000 - that gives us 80% that the candidate will accept the offer, but our payoff is lower, let's say 0.8 (maybe because that will make our profit from this candidate's work smaller, or because it sets a precedence where a new joiner will make more than others, etc.)&lt;/li&gt;
&lt;li&gt;we agree to $150,000 - here we can expect 90% chance that the offer will be accepted, but again our payoff is a bit lower, let's say 0.6&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The percentage here is not given and might vary a lot, the same with the payoff value - it's very hard to predict how a candidate joining us will impact the company. What I'm trying to model here is just a situation where we by sacrificing some value (paying higher salary) we increase the certainty that our offer will be accepted.&lt;/p&gt;

&lt;p&gt;Now let's calculate the expected payoff for each of these 3 strategies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;$130,000: 40% * 1 + 60% * 0 = 0.4&lt;/li&gt;
&lt;li&gt;$140,000: 80% * 0.8 + 20% * 0 = 0.64&lt;/li&gt;
&lt;li&gt;$150,000: 90% * 0.6 + 10% * 0 = 0.63&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, negotiation is the best strategy. Again, these numbers are completely made up, the company has no details about the candidate's situation - maybe the candidate will walk away unless they get $150k, or maybe they're bluffing when they say they have other offers. What the company knows is how much they value the specific candidate and how much they can afford to pay. With this partial information they need to make a choice - and usually being flexible and offering the candidate at least some more salary can make a big difference!&lt;/p&gt;

&lt;p&gt;You can try to model different scenarios and you'll get very different results. If it appears that it's the best not to give candidate more money, look at what made it happen. Is the certainty that candidate will accept the offer anyway very high? Or does the company assign much lower payout if they pay more than the initial offer?&lt;/p&gt;

&lt;h2&gt;
  
  
  To ask for more or not - candidate's perspective
&lt;/h2&gt;

&lt;p&gt;Now let's look at this from the other perspective. Imagine that in our current job we make $100,000, and the company we applied for offers us $130,000. That's quite a difference, 30% bump in salary is a decent number! The question is then whether the negotiation still makes sense.&lt;/p&gt;

&lt;p&gt;We're limit the payoff here purely to the salary and we'll omit other things like how much we like the company, whether it's a good career move etc. Then we have 3 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we accept the offer - with expected payoff equal to $130,000&lt;/li&gt;
&lt;li&gt;we reject the offer - expected payoff is $100,000 (salary at the current company)&lt;/li&gt;
&lt;li&gt;we negotiate the offer and ask for $150,000 - let's try to calculate a potential payoff here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's say we can expect one of 4 responses from the company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they withdraw the offer, which is extremely rare, so we assume there's 1% chance; this will have a payoff of $100,000 (we stay at current job)&lt;/li&gt;
&lt;li&gt;they keep the offer at $130,000, let's say there's 39% chance this will happen&lt;/li&gt;
&lt;li&gt;they raise the offer to $140,000, 40% chance&lt;/li&gt;
&lt;li&gt;they give us $150,000, 20% chance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quick calculation: $100k * 1% + $130k * 39% + $140k * 40% + $150k * 20% = $137,700, a 6% increase over original offer (and we asked for 15% more).&lt;/p&gt;

&lt;p&gt;Again, you can try different numbers - maybe you're asking for 50% higher offer and there's a lower chance that you'll get it? But as long as you know that the chance of losing the offer is very low, you should always see that &lt;strong&gt;it's worth it to negotiate!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to negotiate
&lt;/h2&gt;

&lt;p&gt;As I wrote in the beginning, the topic of negotiation is covered widely in a number of videos, articles, and books. Heck, there are even companies that specialize in helping candidates to negotiate good offers from big tech companies.&lt;/p&gt;

&lt;p&gt;The most important step though is to actually start the negotiation. In the video below I spend a few minutes talking about why you should do it, and then I explain how to start negotiating if you don't feel confident about it. Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/g12Sd4-zRc8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Resources for Engineering Managers</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 10 Aug 2021 11:00:00 +0000</pubDate>
      <link>https://dev.to/gregorywitek/resources-for-engineering-managers-5d47</link>
      <guid>https://dev.to/gregorywitek/resources-for-engineering-managers-5d47</guid>
      <description>&lt;p&gt;On this page I'm collecting a list of various resources for engineering managers. I personally tried/watched/read all of them, except when I explicitly mention that I didn't. Some of the links below might be affiliate links. I'll keep updating the page, I'm currently building a list of articles that I recommend for all EMs, so check it again in the future!&lt;/p&gt;

&lt;p&gt;I'm always eager to try and learn new things, if you have some recommendation, ping me on &lt;a href="https://twitter.com/GregoryWitek"&gt;🐦Twitter&lt;/a&gt; or send me an &lt;a href="//mailto:gregory@notonlycode.org"&gt;✉️email&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Books
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3xqUWIB"&gt;Accelerate: The Science of Lean Software and DevOps&lt;/a&gt; - probably more useful for VPs of Engineering or CTOs, this book talks about introducing Lean and DevOps practices in order to improve the efficiency of tech teams and build more resilient organizations.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3AlQmxq"&gt;Become an Effective Software Engineering Manager&lt;/a&gt; (&lt;a href="https://www.youtube.com/watch?v=MIMDgNxbBqg"&gt;🎥 video&lt;/a&gt;) - great primer on engineering managers' responsibilities, it guides reader through various challenges and recommends how to approach them. Great read!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3ApytxJ"&gt;Behind Closed Doors: Secrets of Great Management&lt;/a&gt; - not specific to tech industry, this book still provides useful advice for managers who want to improve their skills. It covers multiple topics like delegation, coaching, goals&amp;amp;objectives and more&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/2Vq40AP"&gt;The Culture Map&lt;/a&gt; - a business book that talks about working with different cultures. The author is a consultant and shares her lessons about working with companies all over the world, but I found this content very relevant to my work as EM, since I lead international teams and I strive to understand how my team members work&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3lCGICk"&gt;An Elegant Puzzle&lt;/a&gt; - a collection of tools and approaches to various problems you'll encounter in tech leadership role. I recommend it more as a reference book rather than reading cover to cover.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://leadingsnowflakes.com/"&gt;Leading Snowflakes&lt;/a&gt; - a good intro to engineering management; Oren Ellenbogen shares 9 lessons for new EMs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3CsodGA"&gt;Manager's Path&lt;/a&gt; - a book that describes various states and challenges related to management in tech industry, from tech leads to CTOs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3xvzrX9"&gt;Managing Humans&lt;/a&gt; - engineering management stories from Sillicon Valley. I gave it 4 stars on Goodreads, though I read it a long time ago and don't remember much&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/37tpDSU"&gt;Peopleware: Productive Projects and Teams&lt;/a&gt; - a classic book on productivity of software teams. It certainly feels dated (originally released in late 1980s), but 3rd edition was released in 2013 and the book still has a lot of value&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3ix1Sj6"&gt;The Phoenix Project&lt;/a&gt; - a handbook in form of a novel, the book teaches about DevOps practices and looks at managing teams from perspective of inputs and outputs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://abookapart.com/products/resilient-management"&gt;Resilient Management&lt;/a&gt; - a book for new managers, covers topics like setting clear expectations, and effective communication. Currently on my to-read list&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3Aj9XOD"&gt;The Software Engineering Manager Interview Guide&lt;/a&gt; - interview preparation book by Vidal Graupera (whose blog you can also find on this page)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3jEfHMm"&gt;The Unicorn Project&lt;/a&gt; - a sequel (I guess?) to "The Phoenix Project", written in similar style of a novel, this book focuses on good software development practices. In my opinion it's not nearly as good as the first book, but still an entertaining read&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://easyretro.io/"&gt;EasyRetro&lt;/a&gt; (formerly FunRetro) - my tool of choice when it comes to running team retrospectives&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt; - a favourite planning tool of many people, can act as a calendar, todo list, project management tool, and many more; comes with a generous free plan&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md"&gt;Obsidian&lt;/a&gt; - a knowledge base tool that allows you to connect multiple pages witn linking mechanisms. It has a growing community and an ecosystem of plug-ins&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://peakon.com/"&gt;Peakon&lt;/a&gt; - a web-based tool that helps to measure employee engagement, and allows employees to anonymously share feedback with their managers. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.progression.fyi/"&gt;progression.fyi&lt;/a&gt; - a collection of career growth frameworks and matrices, not only for developers, but also testers, project managers, and more. Very useful when you're building a propression framework for your department or company&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sourcelevel.io/"&gt;SourceLevel&lt;/a&gt; - a tool that uses various metrics to allow you to better understand your team's performance (I haven't tried it yet, and I still haven't made up my mind about how useful are such tools)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt; - a powerful todo app with clients for all major operating systems; free plan available&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://typora.io/"&gt;Typora&lt;/a&gt; - a desktop Markdown editor (Windows, MacOS, Linux) with a minimalist style and a lot of very well-thought features. One of my favorites, I use it to write a tech book with a lot of code examples, and to write work-related notes. Currently (August 2021) available for free&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Blogs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://skamille.medium.com"&gt;Camille Fournier&lt;/a&gt; - blog by author of "The Manager's Path". Camille doesn't write often, but when she does, it's high quality content&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://charity.wtf/"&gt;Charity Majors&lt;/a&gt; - tons of thoughts about tech careers and leadership, a must read!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.managersclub.com"&gt;Managers Club&lt;/a&gt; - interviews and articles on engineering management, by Vidal Graupera, author of "&lt;a href="https://amzn.to/3Aj9XOD"&gt;The Software Engineering Manager Interview Guide&lt;/a&gt;"&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.patkua.com/blog"&gt;Pat Kua&lt;/a&gt; - Pat is a coach and consultant and ex-CTO, on his blog he shares thought on the intersection of tech and management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.pragmaticengineer.com"&gt;Pragmatic Engineer&lt;/a&gt; - Gergely Orosz, an experienced engineering manager shares his lessons from Uber and Microsoft, and writes about topics like career progressions and salary negotiations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://svpg.com/articles/"&gt;Silicon Vallye Product Group&lt;/a&gt; - blog focused on product managenemt, with a lot of useful content for engineering managers who closely collaborate with product teams&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lethain.com/"&gt;Will Larson&lt;/a&gt; - author of "An Elegant Puzzle" and "Staff Engineer", Will shares a lot of interesting thoughts on tech careers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Newsletters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://levelup.patkua.com/"&gt;Level Up&lt;/a&gt; - weekly content for leaders in tech by Pat Kua (who also writes a blog I list on this page)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://softwareleadweekly.com/"&gt;software lead weekly&lt;/a&gt; - newsletter by Oren Ellenbogen (author of "Leading Snowflakes" - check books section), with content about people, culture, and leadership in tech. Going strong for more than 400 editions!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ctocraft.com/community/"&gt;Tech Manager Weekly&lt;/a&gt; - another weekly newsletter with interesting articles about managing tech teams. Made by CTO Craft (check also communities section below)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Others
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ctocraft.com/community/"&gt;CTO Craft Community&lt;/a&gt; - CTO Craft is a company offering coaching and workshops for technical leaders. They have a free Slack community and organize a number of events, like conferences&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://engmanagers.github.io/"&gt;Engineering Manager Slack group&lt;/a&gt; - a Slack community moderated by a group of volunteers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ryanburgess/engineer-manager"&gt;https://github.com/ryanburgess/engineer-manager&lt;/a&gt; - a more comprehensive list of resources with 100+ items for engineering managers, though it often lacks any description of an item&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://leaddev.com/"&gt;LeadDev&lt;/a&gt; - LeadDev is a full portal and an organization dedicated for tech leaders. It includes a ton of good articles, they organize events and workshops. Truly a great place for engineering managers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.platohq.com/"&gt;Plato&lt;/a&gt; - a place where you can find mentors (paid service) or volunteer your time to help others. I currently participate there as a mentor.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mentoring-club.com"&gt;Mentoring Club&lt;/a&gt; - a non-profit alternative to Plato, where you can find mentors or become a mentor. I haven't tried it personally yet.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The power of reduce</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 27 Jul 2021 15:45:23 +0000</pubDate>
      <link>https://dev.to/gregorywitek/the-power-of-reduce-55en</link>
      <guid>https://dev.to/gregorywitek/the-power-of-reduce-55en</guid>
      <description>&lt;p&gt;&lt;code&gt;reduce&lt;/code&gt; (aka &lt;code&gt;fold&lt;/code&gt; aka &lt;code&gt;inject&lt;/code&gt; aka &lt;code&gt;lfold&lt;/code&gt;) is a very powerful, flexible, and at the same time an unintuitive and controversial function. In this post I'll talk about what makes it both so flexible and unintuitive, and I'll present how other iteration functions like &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;filter&lt;/code&gt; can be implemented on top of &lt;code&gt;reduce&lt;/code&gt;. I'll use JS definition of &lt;code&gt;reduce&lt;/code&gt; as a reference and I'll show what other languages do better in implementing this function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics of reduce
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;reduce&lt;/code&gt; is a function that works on collections. It usually accepts 2 arguments: a reducer function and an optional initial value. &lt;code&gt;reduce&lt;/code&gt; iterates over the collection, calling the reducer function for every element and passing the output of reducer to the next iteration (with one exception mentioned later). A simple example is calculating a product of all elements of the array:&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;// returns 2 * 4 * 6 * 8 = 384&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;el&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reducer function can accept up to 4 arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accumulator - the output of previous iteration (in the first iteration it takes the default value, or if not provided, the first element of the array)&lt;/li&gt;
&lt;li&gt;element - the current element of the array&lt;/li&gt;
&lt;li&gt;index - the index of the current element of the array&lt;/li&gt;
&lt;li&gt;originalArray - the whole array on which &lt;code&gt;reduce&lt;/code&gt; is being called.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the following example, the execution will look like this:&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="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;st&lt;/span&gt; &lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&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;output&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;2&lt;/span&gt;&lt;span class="nx"&gt;nd&lt;/span&gt; &lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;rd&lt;/span&gt; &lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;rd&lt;/span&gt; &lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to understand it better and see more advanced examples, check the tutorial I recorded:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/UxaAAMSgQuo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;reduce&lt;/code&gt; has traditionally been a part of functional languages, where it acts as kind of equivalent of &lt;code&gt;for&lt;/code&gt; loops. It became more common thanks to a MapReduce framework which allows to easily parallelize operations that aggregate some data. MapReduce splits the work to be done in 2 parts - &lt;code&gt;map&lt;/code&gt; part performs some kind of operation on each piece of data (this part can be done in parallel) and &lt;code&gt;reduce&lt;/code&gt; then gathers all the output from &lt;code&gt;map&lt;/code&gt; and combines the filan result (this part is done sequentially).&lt;/p&gt;

&lt;p&gt;Let's say we want to count number of occurences of each word in a piece of text. We can split the text into sentences, and fo each sentence we can calculate number of occurences of each word in parallel. Then we end up with multiple dictionaries, let's say:&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="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;animal&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;and&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mammal&lt;/span&gt;&lt;span class="dl"&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="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fish&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;animal&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;too&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;reduce&lt;/code&gt; function can merge these 2 dictionaries and calculate final output:&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="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;animal&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;and&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mammal&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fish&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;too&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, &lt;code&gt;reduce&lt;/code&gt; does not need &lt;code&gt;map&lt;/code&gt; to achieve the result above - it's only needed in order to have the first part run in parallel.&lt;/p&gt;

&lt;p&gt;Another common use case is to calculate some number that's based on a list of numbers. A good example is sum of squares that has a number of uses in mathematics like in linear regression.&lt;/p&gt;

&lt;p&gt;I personally often use &lt;code&gt;reduce&lt;/code&gt; in order to transform one dictionary into another (e.g. I might need to normalize keys, or update values). This is not possible in JavaScript though - I explain it a bit later in the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  The controversy
&lt;/h2&gt;

&lt;p&gt;For a number of reasons, &lt;code&gt;reduce&lt;/code&gt; is a controversial function among programmers. In JS it gets quite a bad rep, like in the widely retweeted example below:&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ynOngITX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1695239906/me_normal.jpg" alt="Jake Archibald profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jake Archibald
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @jaffathecake
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      All code using array.reduce should be rewritten without array.reduce so it's readable by humans *mutes thread*
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      12:40 PM - 03 Jan 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1213077702300852224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1213077702300852224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1213077702300852224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;It's not the only example, though. In Python, &lt;code&gt;reduce&lt;/code&gt; was removed from the standard library and moved to &lt;code&gt;functools&lt;/code&gt; library. It's still shipped as part of the Python language distribution, but in order to use it, you need to explicitly import it.&lt;/p&gt;

&lt;p&gt;There are a number of reasons why &lt;code&gt;reduce&lt;/code&gt; gets a bad reputation, the main of them being: for every use of &lt;code&gt;reduce&lt;/code&gt; there's at least one more intuitive and more readable alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  For loops and other options
&lt;/h3&gt;

&lt;p&gt;First argument for not using &lt;code&gt;reduce&lt;/code&gt; is that many languages (mainly imperative/OO) there are always more idiomatic and intuitive ways to write code than useing &lt;code&gt;reduce&lt;/code&gt;. The main solution is to use &lt;code&gt;for&lt;/code&gt; loop, &lt;code&gt;forEach&lt;/code&gt; function, or some kind of equivalent. Let's take the example from the previous section:&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="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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;el&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to write is&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&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="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;el&lt;/span&gt; &lt;span class="k"&gt;in&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="nx"&gt;el&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 programmers coming from other imperative languages, the latter version certainly feels more familiar. Is it clearly better though? I'm not so sure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Readability
&lt;/h3&gt;

&lt;p&gt;The second argument is quite similar, but focuses on &lt;code&gt;reduce&lt;/code&gt; function itself - a lot of people say the function is hard to read. I partially agree with this. Most of the time I have little problem understanding what is the goal of &lt;code&gt;reduce&lt;/code&gt; just by having a quick look, but because it can return anything, it's not as meaningful and intuitive as &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;filter&lt;/code&gt;. What's more, if you want to use &lt;code&gt;reduce&lt;/code&gt; in multiple programming languages, you'll have to remember that each of them has a different number and order of arguments!&lt;/p&gt;

&lt;p&gt;There's one more thing that adds to the problem - the initial value, which is an optional parameter in &lt;code&gt;reduce&lt;/code&gt; and which changes a lot about how the function works. If you have a collection of 10 elements, you can expect that it'll trigger 10 iterations, however if you don't pass the initial value to the function, there'll be only 9 iterations. That's because the first element of the collection will become the initial value. In a lot of cases, like when calculating a sum or a product, it doesn't matter, but when you want to calculate sum of squares, that missing initial value will break the function!&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sumSquares&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;sumSquares&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;// =&amp;gt; 30, works!&lt;/span&gt;
&lt;span class="nx"&gt;sumSquares&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="mi"&gt;3&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;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 18, broken!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;The last reason applies to some specific langauges, for example JavaScript - &lt;code&gt;reduce&lt;/code&gt; was added to JS as a half-baked thing, working only on arrays. The same function in other languages can be used on other types of collections. In Ruby as long as a class includes the &lt;code&gt;Enumerable&lt;/code&gt; module, it gets &lt;code&gt;reduce&lt;/code&gt; function. In Python, where &lt;code&gt;reduce&lt;/code&gt; is used very rarely, you still can use it with dictionaries. I believe &lt;code&gt;reduce&lt;/code&gt; would be way more useful in JavaScript if only it was possible to call it on other types of collections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write everything in reduce!
&lt;/h2&gt;

&lt;p&gt;While I agree with the arguments I presented above, I still believe that understanding &lt;code&gt;reduce&lt;/code&gt; can be very helpful, especially if you ever consider learning functional languages. It's really a powerful function. Actually, &lt;code&gt;reduce&lt;/code&gt; is so flexible, that a lot of collection functions can be rewritten using &lt;code&gt;reduce&lt;/code&gt;. Let's try it out!&lt;/p&gt;

&lt;p&gt;Warning: don't try to do it in your apps. The original implementations of the functions below are certainly better (and probably much, much faster).&lt;/p&gt;

&lt;h3&gt;
  
  
  forEach
&lt;/h3&gt;

&lt;p&gt;First, something easy: &lt;code&gt;forEach&lt;/code&gt; is a &lt;code&gt;reduce&lt;/code&gt; that calls a passed callback and does not return any value.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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;h3&gt;
  
  
  map
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;map&lt;/code&gt; is &lt;code&gt;reduce&lt;/code&gt; where we start with empty array and in every iteration we add result of the callback function to the accumulator.&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="kd"&gt;function&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;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A slightly more readable (and faster, I guess) version, with 2 statements, would look like this:&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="kd"&gt;function&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;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  flatMap
&lt;/h3&gt;

&lt;p&gt;This one's quite complicated! &lt;code&gt;flatMap&lt;/code&gt; behaves similarly to &lt;code&gt;map&lt;/code&gt; except that it always returns a flat (1-dimensional) array. If the provided callback returns an array, map returns an array of arrays, while &lt;code&gt;flatMap&lt;/code&gt;, as the name suggests, flattens the output. It could be implemented this way:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if the &lt;code&gt;cb&lt;/code&gt; does not return an array (we can't guarantee it does), we need to add something more. There are a few different ways to deal with it, the most trivial is to just flatten the outer array. It's not a pretty solution (and oh it is SO slow), but it will do.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nx"&gt;flatten&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  filter
&lt;/h3&gt;

&lt;p&gt;Next, &lt;code&gt;filter&lt;/code&gt; returns elemets of orignal array, but only those that meet the provided expectation (read: where &lt;code&gt;cb(el)&lt;/code&gt; returns truthy value). First, let me implement it using 2 statements to make it easier to read.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the same can be rewritten with a single statement, though it's less intuitive.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  some
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;some&lt;/code&gt; returns true if callback function returns &lt;code&gt;true&lt;/code&gt; (or any truthy value) for any of the elements in the array. It can be written in pseudocode as &lt;code&gt;cb(array[0]) || cb(array[1]) || ... || cb(array[n-1])&lt;/code&gt;. In order to implement it with &lt;code&gt;reduce&lt;/code&gt; I'll be carrying on the boolean value over each iteration.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="kc"&gt;false&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;h3&gt;
  
  
  every
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;every&lt;/code&gt; is a sibling function to &lt;code&gt;some&lt;/code&gt; and returns &lt;code&gt;true&lt;/code&gt; if the callback function returns &lt;code&gt;true&lt;/code&gt; for every element of the array. It can be written as &lt;code&gt;fun(array[0]) &amp;amp;&amp;amp; fun(array[1]) &amp;amp;&amp;amp; ... &amp;amp;&amp;amp; fun(array[n-1])&lt;/code&gt;. Similarly I'll carry a boolean value as &lt;code&gt;acc&lt;/code&gt;.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="kc"&gt;true&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;h3&gt;
  
  
  includes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;includes&lt;/code&gt; could actually be implemented using &lt;code&gt;some&lt;/code&gt;. For the sake of consistency I'll just keep using the &lt;code&gt;reduce&lt;/code&gt; directly though. In this case we don't have a callback to use, instead we need to check if any element is equal to provided value.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kc"&gt;false&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;As a side note, the 3 functions above are examples where using &lt;code&gt;reduce&lt;/code&gt; introduces a performance penalty (they'll iterate over the whole array even if they could stop earlier). One more reason not to use this code in any serious application.&lt;/p&gt;

&lt;h3&gt;
  
  
  find
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;find&lt;/code&gt; returns the first element that meets a criteria specified by the callback function. In terms of implementation, it's similar to &lt;code&gt;some&lt;/code&gt; with a twist. Just like with &lt;code&gt;some&lt;/code&gt; we're going to pass a certain falsy value and as soon as it becomes truthy, we're going to pass it till the end of the iteration process. The twist is that the value we need to pass is not the output of the callback function, but the element on which the function is called.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;null&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;Earlier in this post I said I'd try to write the &lt;code&gt;reduce&lt;/code&gt; with only a single expression. It's possible in this case as well, though just as before it's harder to understand:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="kc"&gt;null&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;The &lt;code&gt;cb(el) &amp;amp;&amp;amp; el&lt;/code&gt; part will return &lt;code&gt;false&lt;/code&gt; if the element does not meet provided requirement, or it will return the value of &lt;code&gt;el&lt;/code&gt; if it does. Then the first part, &lt;code&gt;acc || ...&lt;/code&gt;will either return &lt;code&gt;acc&lt;/code&gt; (output of previous iteration), unless it's a falsy value, in which case it'll return the 2nd part explained above.&lt;/p&gt;

&lt;h3&gt;
  
  
  findIndex
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;findIndex&lt;/code&gt; initially seemed more challenging to implement, because somehow I need to keep track of the index together with the element. Then I remembered that the reducer function takes 4 arguments, and not only 2! The 3rd argument is the current index, and 4th one is the array on which the &lt;code&gt;reduce&lt;/code&gt; is called (I'm still thinking how to use it in practice). So &lt;code&gt;findIndex&lt;/code&gt; will be almost identical to &lt;code&gt;find&lt;/code&gt;.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;null&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;h3&gt;
  
  
  lastIndexOf
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;lastIndexOf&lt;/code&gt; is almost the same, except that first we check whether the current element meets the expectation, and only if it doesn't, then we return the last on that did. In short: we swap the order.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;null&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;Similarly to &lt;code&gt;find&lt;/code&gt;, the &lt;code&gt;findIndex&lt;/code&gt; and &lt;code&gt;lastIndexOf&lt;/code&gt; functions (why isn't it called &lt;code&gt;findLastIndex&lt;/code&gt; by the way? and why there's no &lt;code&gt;findLast&lt;/code&gt; function?) could be rewritten using a single expression, the only difference is the order and the logical operators used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can reduce do everything?
&lt;/h2&gt;

&lt;p&gt;Looking at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"&gt;the list of array functions in JS&lt;/a&gt; and I was wondering if there's anything that &lt;strong&gt;can't&lt;/strong&gt; be implemented with &lt;code&gt;reduce&lt;/code&gt;. Initially I had 3 ideas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Functions that modify the original array - &lt;code&gt;reduce&lt;/code&gt; comes from languages with immutable data structures, so modifying original array (with functions like &lt;code&gt;copyWithin&lt;/code&gt;) was a long shot, but because the reducer accepts original array as a parameter, it is possible (I am 99.99% sure it's always bad idea, though - don't do it at home!)&lt;/li&gt;
&lt;li&gt;Sorting - ok, when that idea came to my mind I thought it was really stupid, but maybe it's possible to implement some kind of bubble sort with &lt;code&gt;reduce&lt;/code&gt;? Well, it seems &lt;a href="https://stackoverflow.com/questions/50245957/sorting-array-with-javascript-reduce-function"&gt;I was not the only person who wondered about it&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Finally, I found something - &lt;code&gt;Array&lt;/code&gt; class has methods like &lt;code&gt;keys&lt;/code&gt; and &lt;code&gt;entries&lt;/code&gt;, and those functions return iterators. I tried to implement them with &lt;code&gt;reduce&lt;/code&gt;, but I failed miserably, so I assume it can't be done (correct me if I'm wrong!).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's the point?
&lt;/h2&gt;

&lt;p&gt;This was a fun exercise, but my point here is that each function has its place. &lt;code&gt;reduce&lt;/code&gt; gets a lot of bad rep in JS and for good reasons. It's limiting yet overcomplicated and I still don't remember the order of parameters in reducer, although I used it a number of times. Still, it's good to understand it, so that you can use it from time to time.&lt;/p&gt;

&lt;p&gt;Oh, and of course - check out other languages where &lt;code&gt;reduce&lt;/code&gt; work also for dictionaries, sets, or other collection types. Languages like Elixir, Haskell or Ruby make &lt;code&gt;reduce&lt;/code&gt; more powerful and intuitive at the same time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Become a Productive Programmer</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Sat, 24 Jul 2021 13:47:59 +0000</pubDate>
      <link>https://dev.to/gregorywitek/become-a-productive-programmer-1c6d</link>
      <guid>https://dev.to/gregorywitek/become-a-productive-programmer-1c6d</guid>
      <description>&lt;p&gt;In this video I'm talking about how to become a more productive programmer. Productivity is always a hot topic and it's something that a lot of developers struggle with. In order to become a productive developer you'll need to put in a lot of effort, but there are some ways to improve the way you work even in environments full of distractions!&lt;/p&gt;

&lt;p&gt;🎥 Timeline&lt;br&gt;
0:00 intro&lt;br&gt;
0:30 deep work, shallow work&lt;br&gt;
1:58 tip #1 - good preparation&lt;br&gt;
3:57 tip #2 - own your calendar&lt;br&gt;
8:27 tip #3 - split your tasks&lt;br&gt;
9:56 why pomodoro technique doesn't work&lt;br&gt;
10:47 working in a team&lt;br&gt;
11:47 magic productivity techniques&lt;br&gt;
12:44 Outro&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Engineering manager interview - questions and preparation</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 29 Jun 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/gregorywitek/engineering-manager-interview-questions-and-preparation-2cfe</link>
      <guid>https://dev.to/gregorywitek/engineering-manager-interview-questions-and-preparation-2cfe</guid>
      <description>&lt;p&gt;Engineering manager role comes in a lot of flavours and the interview processes for this role at various companies reflect that differences. In this video I'm talking about what kind of interviews and questions you can expect, and below the video you can find a list of questions that you might hear during different interview rounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/leBL1fw-WJg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;🎥 timeline:&lt;/p&gt;

&lt;p&gt;0:00 developer interview vs manager interview&lt;br&gt;&lt;br&gt;
0:59 programming interview&lt;br&gt;&lt;br&gt;
02:20 system design interview&lt;br&gt;&lt;br&gt;
03:36 system design - how to prepare&lt;br&gt;&lt;br&gt;
05:30 team management interview&lt;br&gt;&lt;br&gt;
07:25 stakeholder management interview&lt;br&gt;&lt;br&gt;
08:20 management interview - how to prepare&lt;br&gt;&lt;br&gt;
11:05 general interview tips&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;what is your leadership style?&lt;/li&gt;
&lt;li&gt;how do you define a successful team?&lt;/li&gt;
&lt;li&gt;have you ever had a very high performing team? what made the team work so well together?&lt;/li&gt;
&lt;li&gt;how do you define an individual success?&lt;/li&gt;
&lt;li&gt;what does it mean to be a successful engineering manager?&lt;/li&gt;
&lt;li&gt;how do you onboard a new team member?&lt;/li&gt;
&lt;li&gt;how do you measure individual performance in your team?&lt;/li&gt;
&lt;li&gt;have you ever taken a struggling project and turned it around? how did you it?&lt;/li&gt;
&lt;li&gt;have you ever had a very urgent situation when you had to make a quick decision? what was that and what did you do?&lt;/li&gt;
&lt;li&gt;have you ever had an underperforming team member? what did you do about it?&lt;/li&gt;
&lt;li&gt;have you ever had to put someone on PIP?&lt;/li&gt;
&lt;li&gt;have you ever had a person that was difficult to work with? what did you do about it?&lt;/li&gt;
&lt;li&gt;have you ever had to let go a member of your team?&lt;/li&gt;
&lt;li&gt;have you ever had a conflict between your team members? how did you deal with it?&lt;/li&gt;
&lt;li&gt;have you ever had a conflict between you and some stakeholder? how did you solve it?&lt;/li&gt;
&lt;li&gt;how do you keep track of ongoing work in your team?&lt;/li&gt;
&lt;li&gt;are you familiar with agile methodologies?&lt;/li&gt;
&lt;li&gt;have you ever led a project that failed? what made it fail? what did you learn from it?&lt;/li&gt;
&lt;li&gt;have you ever made a decision that your team didn't like?&lt;/li&gt;
&lt;li&gt;have you ever managed people who are way more experienced than you? how did you help them succeed in their roles?&lt;/li&gt;
&lt;li&gt;do you do 1-1 meetings with your team members? how do you do it?&lt;/li&gt;
&lt;li&gt;have you ever managed a team budget? how did you keep track of it?&lt;/li&gt;
&lt;li&gt;have you ever promoted a team member? how did you help them progress?&lt;/li&gt;
&lt;li&gt;have you ever denied someone a promotion? how did you explain it to them?&lt;/li&gt;
&lt;li&gt;have you ever had to manage multiple urgent tasks? how did you do that?&lt;/li&gt;
&lt;li&gt;have you ever had to manage unclear product requirements? how did you do it?&lt;/li&gt;
&lt;li&gt;have you ever worked with UX designers/Technical Writers/testers/product managers? How did you ensure that you worked well together?&lt;/li&gt;
&lt;li&gt;have you ever built a team from scratch? how did you do it?&lt;/li&gt;
&lt;li&gt;have you ever managed a fully distributed team? how did you ensure the team was successful?&lt;/li&gt;
&lt;li&gt;have you ever had a toxic team member? how did you handle it?&lt;/li&gt;
&lt;li&gt;have you ever dealt with legacy software? how did you balance between technical debt and feature work?&lt;/li&gt;
&lt;li&gt;have you ever dealt with suddenly changing requirements? what did you do about it?&lt;/li&gt;
&lt;li&gt;have you ever worked with Scrum/Kanban/SAFe etc? How do you understand your role in that methodology?&lt;/li&gt;
&lt;li&gt;have you ever dealt with project that missed its deadline? what did you do about it?&lt;/li&gt;
&lt;li&gt;have you ever made a bad decision that affected your team? how did you resolve the situation?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll keep updating this post with more questions in the future, and if you have some suggestions, leave them in the comments!&lt;/p&gt;

</description>
      <category>career</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Python gotchas for JavaScript developers</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Mon, 11 Jan 2021 18:53:12 +0000</pubDate>
      <link>https://dev.to/gregorywitek/python-gotchas-for-javascript-developers-32d9</link>
      <guid>https://dev.to/gregorywitek/python-gotchas-for-javascript-developers-32d9</guid>
      <description>&lt;p&gt;If you're a JavaScript developer who's interested in topics like machine learning, data science, or even if you want to learn some new tool to broaden your experience, there's a high chance that you are trying out (or going to try out) Python. While both languages are quite similar, there are a bunch of surprising differences that can confuse you. In this article I list a couple of such gotchas together with examples and explanations which will help you understand why both languages behave differently.&lt;/p&gt;

&lt;p&gt;And if you are looking for a new language to learn as a JavaScript developer, &lt;a href="https://dev.to/gregorywitek/choose-your-next-programming-language-1ab1"&gt;check out my video where I talk about how to choose your next language&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anonymous functions are very limited
&lt;/h2&gt;

&lt;p&gt;First on the list: anonymous functions aka closures aka lambdas. They're a very common tool in JavaScript. To be fair they'r nothing special, just ad-hoc created functions that do not have any specific name. Any time you write &lt;code&gt;array.map((el) =&amp;gt; doSomething(el))&lt;/code&gt; you write an anonymous function. Heck, to be fair probably 99% of JS functions you write these days are technically  anonymous. Look at this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I have no name!&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;otherFun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Me neither!&lt;/span&gt;&lt;span class="dl"&gt;"&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;These 2 functions are anonymous. You can refer to them via variable to which they're assigned, but if that variable ever changes the value, you can't find the function again, it's lost. In order to have a "real" named function, you need to do this:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I have a name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;otherFun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Me too!&lt;/span&gt;&lt;span class="dl"&gt;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are certain other differences between named and anonymous functions in JS, but in general they're very similar and you can easily use either of them most of the time. However, in Python the situation is different. While the language supports both named and anonymous functions, the latter are very limited: they can consist of only one expression (essentially they can do one operation). To show you an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fun1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"works!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fun2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="n"&gt;wrongFun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# this will throw invalid syntax error!
&lt;/span&gt;    &lt;span class="n"&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="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that the following piece of code is impossible to write using lambdas in Python:&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="nx"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;logOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;saveContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&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;Why is there such limitation? As &lt;a href="https://www.artima.com/weblogs/viewpost.jsp?thread=147358"&gt;Python's creator himself explains&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I find &lt;em&gt;any&lt;/em&gt; solution unacceptable that embeds an indentation-based block in the middle of an expression.  Since I find alternative syntax for statement grouping (e.g. braces or begin/end keywords) equally unacceptable, this pretty much makes a multi-line lambda an unsolvable puzzle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically in order to allow multi-line anonymous functions, a single expression would need to respect the tab-based indendation rules (currently it doesn't) or use another block separators (like &lt;code&gt;{}&lt;/code&gt; in JS). Guido van Rossum, creator of the language, rejected both these ideas.&lt;/p&gt;

&lt;p&gt;What's the solution then? Well, simply give the function a name! To be fair it's not that much of a deal, rather an inconvenience, but also a gotcha, something that I didn't expect when I first learned Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RfEaBTSL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/01/nightclub-anonymous.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RfEaBTSL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/01/nightclub-anonymous.png" alt="Python gotchas for JavaScript developers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Expressions vs statements
&lt;/h2&gt;

&lt;p&gt;Related to the previous point are differences between statements and expressions in both languages. If you're not sure what are these two, a brief explanation is that expression is something that produces a value, while statement is just a piece of code that performs something, but it does not return any value. In other words, you can ask yourself: &lt;strong&gt;can I assign it to a variable? If yes, it's an expression, otherwise it's a statement&lt;/strong&gt;. For example:&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="kd"&gt;const&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;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3 is an expression&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&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;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// arithmetic operations are expressions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (z = 10) is also an expression&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&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;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;// this won't work! if is a statement&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myFun&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// calling a function is an expression&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so what's the issue? Well, the issue is that an expression in JavaScript might not be an expression in Python! For example, creating a function:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&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;sthElse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;namedFun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;7&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;This code is perfectly valid in JavaScript (even if it's not common to assign named functions to variables). What about Python?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# this code is valid
&lt;/span&gt;&lt;span class="n"&gt;sthElse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;namedFun&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# this code will crash!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case the 2nd example does not work, because defining a named function in Python is a statement, not an expression. Similarly with assignments &lt;code&gt;let a = 10&lt;/code&gt; in JS returns &lt;code&gt;10&lt;/code&gt;, while in Python &lt;code&gt;a = 10&lt;/code&gt; returns nothing, it does not produce any value.&lt;/p&gt;

&lt;p&gt;I am not sure why Python function definition is a statement. A possible explanation is that on one hand indented lines inside an expression do not create a new scope (which is logical, why would they) and on the other hand function definition must create a new scope, therefore a function definition can't be an expression. That's just my theory though, maybe it was decided a priori that definition is a statement and that's it.&lt;/p&gt;

&lt;p&gt;I can't think of any more diffecentec between expressions and statements in Python vs JavaScript, but if you're interested in how it looks in other languages you can check Ruby, where essentially everything is an expression (including &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; etc).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WRs70end--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/01/superman-expression.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WRs70end--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.notonlycode.org/content/images/2021/01/superman-expression.png" alt="Python gotchas for JavaScript developers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tricky default parameters
&lt;/h2&gt;

&lt;p&gt;Default values for function arguments are a feature so obvious that it is rarely ever mentioned besides basic tutorials. It's easy, if a value is not passed to your function explicitly, instead of throwing an error, you just give it a certain, hardcoded value.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;processJob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;startIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;processJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ian&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// run in 60sec&lt;/span&gt;
&lt;span class="nx"&gt;processJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createUses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// run now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Python, default values have a catch though - instead of being evaluated every time a function is called, &lt;strong&gt;default values are evaluated only once&lt;/strong&gt;. Why does it matter? Because if you decide to modify the argument inside your function, it will not be brought back to its previous state! Let me show it using an example. First, JavaScript:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;addOne&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;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// returns [3,2,1]&lt;/span&gt;
&lt;span class="nx"&gt;addOne&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;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// returns [3,2,1] again&lt;/span&gt;

&lt;span class="nx"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// returns [1]&lt;/span&gt;
&lt;span class="nx"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// returns [1] again, this is crucial here    &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets compare it with Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt;
    &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;

&lt;span class="n"&gt;addOne&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;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# returns [3,2,1]
&lt;/span&gt;&lt;span class="n"&gt;addOne&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;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# returns [3,2,1]
&lt;/span&gt;
&lt;span class="n"&gt;again&lt;/span&gt; &lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# returns [1]
&lt;/span&gt;&lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# BOOM! returns [1,1]
&lt;/span&gt;&lt;span class="n"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# and now returns [1,1,1]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the difference? &lt;strong&gt;The default argument is always the same array&lt;/strong&gt;. Unlike most of the languages I know, Python does not recreate this object every time. The common solution to this problem is unfortunately a rather ugly idiom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
         &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

     &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this difference applies only to complex data types like arrays, dictionaries etc. If your argument is a string or a number, the default value will not change from one call to another, so you can safely use it. However if you want to have an array or dictionary by default, you need to pass &lt;code&gt;None&lt;/code&gt; as a default value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nothing is private!
&lt;/h2&gt;

&lt;p&gt;Alright, there are way more examples, but let's not turn this article into a compedium. Let me just mention one last gotcha in this post - privacy... or rather lack of it. As you probably know, JavaScript does not have an explicit concept of private methods or variables. I mean whatever you put in a class can technically be accessed outside of it. &lt;a href="https://github.com/tc39/proposal-private-methods"&gt;There is a proposal&lt;/a&gt; to turn add private methods and fields with kind of an unusual syntax, but for now it's not there yet.&lt;/p&gt;

&lt;p&gt;Still, there are ways to make some stuff kind of private in JS. For example you can write a set of functions and variables and &lt;code&gt;export&lt;/code&gt; only a few of them:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&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;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;pubFun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&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;priFun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;private&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&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="nx"&gt;pubFun&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And of course you can use Typescript, &lt;a href="https://www.typescriptlang.org/docs/handbook/classes.html"&gt;which has a full Java-ish (C++-ish?) set of function/field access control&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, in Python essentially everything is accessible - there is no built-in protection mechanism. There is no &lt;code&gt;export&lt;/code&gt; keyword - everything can be imported from any module, everything can be accessed in any class. Python promotes an "unwritten agreement" approach, where underscores used as prefixes indicate that the function or variable should not be used outside of its original class or module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# go ahead, use it whenever you need
&lt;/span&gt;&lt;span class="n"&gt;_var2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# should not be used outside of its class/module
&lt;/span&gt;&lt;span class="n"&gt;__var3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# DEFINITELY should not be touched
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be precise, Python does a little bit to discourage use of functions with double underscore (&lt;a href="https://stackoverflow.com/questions/17193457/private-methods-in-python"&gt;read more about it here&lt;/a&gt;), but you still can use "private" functions whenever you want, wherever you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  More gotchas?
&lt;/h2&gt;

&lt;p&gt;Programming languages are very complex tools and therefore have a lot of surprises. Sometimes they're obvious and we learn them very early and sometimes it takes months or even years to notice a behavior that surprises us. I'm sure Python has more getchas for JS developers. If you have some other examples, tell me!&lt;/p&gt;

&lt;p&gt;And if you're curious about why Python became such a popular language, &lt;a href="https://dev.to/gregorywitek/why-python-has-won-among-dynamic-languages-joi"&gt;check out my other post where I compare it to other dynamic, scripting languages&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>What *human* language do you write your code in?</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Wed, 30 Dec 2020 21:52:26 +0000</pubDate>
      <link>https://dev.to/gregorywitek/what-human-language-do-you-write-your-code-in-10ab</link>
      <guid>https://dev.to/gregorywitek/what-human-language-do-you-write-your-code-in-10ab</guid>
      <description>&lt;p&gt;Hi folks, a question just popped to my mind and I wanted to ask a broader audience: when writing code, do you name your variables/functions/classes etc using English or your native (or yet some other) language and why?&lt;/p&gt;

&lt;p&gt;I'm asking cause I have seen at a couple examples in my career where people used language other than English and I'm curious how common it is.&lt;/p&gt;

&lt;p&gt;The most obvious argument for using native language is that it's all easier to understand and especially for people who are not very fluent in English, coming up with proper names for functions in English might be challenging.&lt;/p&gt;

&lt;p&gt;On the other side using another language causes a linguistic mix - we all probably use languages that have English keyword, so that means that all built-in functions and 3rd party functions are in English, while our own ones are not, which might make it more challenging to read.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
    </item>
    <item>
      <title>What does an Engineering Manager do?</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 29 Dec 2020 23:45:21 +0000</pubDate>
      <link>https://dev.to/gregorywitek/what-does-an-engineering-manager-do-31jf</link>
      <guid>https://dev.to/gregorywitek/what-does-an-engineering-manager-do-31jf</guid>
      <description>&lt;p&gt;In this video I'm talking abouet engineering management - who is an engineering manager? What does an engineering manager do? Do engineering managers write code? After a short walk around Amsterdam I'm going to tell you about different hats that engineering managers need to wear depending on kind of a company they work for.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/FU2dT-amY-o"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the video I mention article by Pat Kua that I highly recommend: 📝 &lt;a href="https://dev.to5%20Engineering%20Manager%20Archetypes"&gt;https://www.patkua.com/blog/5-engineering-manager-archetypes/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If one day you want to become an engineering mananger you might be interested in following books:&lt;br&gt;&lt;br&gt;
📚 Leading Snowflakes by Oren Ellenbogen - &lt;a href="https://leadingsnowflakes.com/"&gt;https://leadingsnowflakes.com/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
📚 The Manager's Path by Camille Fournier - &lt;a href="https://www.goodreads.com/book/show/33369254-the-manager-s-path"&gt;https://www.goodreads.com/book/show/3...&lt;/a&gt;&lt;br&gt;&lt;br&gt;
📚Management 3.0 bu Jurgen Appelo - &lt;a href="https://www.goodreads.com/book/show/10210821-management-3-0"&gt;https://www.goodreads.com/book/show/1...&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎥 Video timeline 🎥&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FU2dT-amY-o&amp;amp;t=0s"&gt;0:00&lt;/a&gt; Intro and walk around Amsterdam&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FU2dT-amY-o&amp;amp;t=120s"&gt;2:00&lt;/a&gt; 4 hats engineering managers wear&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FU2dT-amY-o&amp;amp;t=309s"&gt;5:09&lt;/a&gt; What does it mean to manage people&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FU2dT-amY-o&amp;amp;t=565s"&gt;9:25&lt;/a&gt; Where is the engineering in engineering manager?&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FU2dT-amY-o&amp;amp;t=724s"&gt;12:04&lt;/a&gt; Outro&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>How I got my first jobs as a sofware developer</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 22 Dec 2020 16:25:26 +0000</pubDate>
      <link>https://dev.to/gregorywitek/how-i-got-my-first-jobs-as-a-sofware-developer-14m6</link>
      <guid>https://dev.to/gregorywitek/how-i-got-my-first-jobs-as-a-sofware-developer-14m6</guid>
      <description>&lt;p&gt;In this video I'm talking about how I got my first few programming jobs. Early in my career I switched jobs a couple of times and I landed all the jobs in a different way, usually by some kind of a reference or cold mail, never by direct application (though I did it later in my career).&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/saBZV12XR9I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;🎥 Video timeline: 🎥&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=0s"&gt;0:00&lt;/a&gt; Intro&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=52s"&gt;0:52&lt;/a&gt; First job (Netguru, Poland)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=210s"&gt;3:30&lt;/a&gt; Second job (Flywire, Spain)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=376s"&gt;6:16&lt;/a&gt; Third job (Fyber, Germany)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=436s"&gt;7:16&lt;/a&gt; Fourth job (freelancing)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=saBZV12XR9I&amp;amp;t=485s"&gt;8:05&lt;/a&gt; Fifth job (Ascenda, Singapore)&lt;/p&gt;

&lt;p&gt;If you enjoy this video, don't forget to subscribe to my &lt;a href="https://www.youtube.com/channel/UCj3PDQ-4n9sO0j3t2j608WQ"&gt;Youtube channel&lt;/a&gt; and make sure to follow me on &lt;a href="https://twitter.com/gregorywitek"&gt;Twitter&lt;/a&gt;. Cheers!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Finding job as a junior developer - tips from tech recruiters</title>
      <dc:creator>Gregory Witek</dc:creator>
      <pubDate>Tue, 15 Dec 2020 17:18:37 +0000</pubDate>
      <link>https://dev.to/gregorywitek/finding-job-as-a-junior-developer-tips-from-tech-recruiters-216a</link>
      <guid>https://dev.to/gregorywitek/finding-job-as-a-junior-developer-tips-from-tech-recruiters-216a</guid>
      <description>&lt;p&gt;Alright junior devs, here's one especially for you! This is the last, bonus episode of the job hunting series and it's dedicated towards junior developers.&lt;/p&gt;

&lt;p&gt;We know that right now finding job as a junior developer is tough - there are fewer opportunities and more candidates. So during the 4 interviews I did for this series I asked one more question: what advice do you have specifically for junior devlopers? This video is a compilation of the answers I got, you'll find here tips from tech recruiters and hiring managers specifically for junior devs.&lt;/p&gt;

&lt;p&gt;Let me know what you think if you have any questions about getting job as a junior dev, reach out to me or drop a comment. Take care!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/w-4P7nz0Fa8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;🎥 Video timeline:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=0s"&gt;0:00&lt;/a&gt; Intro&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=57s"&gt;0:57&lt;/a&gt; Job application (Angus Mackintosh)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=158s"&gt;2:38&lt;/a&gt; Tech interview (Bart van de Garde)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=274s"&gt;4:34&lt;/a&gt; HR interview (Ross Inman)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=378s"&gt;6:18&lt;/a&gt; Offer negotiation (Matthew Barr)&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=w-4P7nz0Fa8&amp;amp;t=482s"&gt;8:02&lt;/a&gt; Outro&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
