<?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: Tom Deneire ⚡</title>
    <description>The latest articles on DEV Community by Tom Deneire ⚡ (@tomdeneire).</description>
    <link>https://dev.to/tomdeneire</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%2F1024687%2F460a01c1-396e-429e-98cc-11bfca9a2307.png</url>
      <title>DEV Community: Tom Deneire ⚡</title>
      <link>https://dev.to/tomdeneire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tomdeneire"/>
    <language>en</language>
    <item>
      <title>It’s 2023: are we still fighting the editor war?</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 25 Feb 2023 15:04:53 +0000</pubDate>
      <link>https://dev.to/tomdeneire/its-2023-are-we-still-fighting-the-editor-war-5h0d</link>
      <guid>https://dev.to/tomdeneire/its-2023-are-we-still-fighting-the-editor-war-5h0d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7680%2F1%2AZDfpPfyymyvRNKprxOdF7Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7680%2F1%2AZDfpPfyymyvRNKprxOdF7Q.png" alt="Screenshot of my editor setup, using [Neovim](https://neovim.io/) with [gopls](https://pkg.go.dev/golang.org/x/tools/gopls) LSP, inside [Tilix](https://gnunn1.github.io/tilix-web/). See my configuration [dotfiles](https://github.com/TomDeneire/nvim)." width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of my editor setup, using &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;Neovim&lt;/a&gt; with &lt;a href="https://pkg.go.dev/golang.org/x/tools/gopls" rel="noopener noreferrer"&gt;gopls&lt;/a&gt; LSP, inside &lt;a href="https://gnunn1.github.io/tilix-web/" rel="noopener noreferrer"&gt;Tilix&lt;/a&gt;. See my configuration &lt;a href="https://github.com/TomDeneire/nvim" rel="noopener noreferrer"&gt;dotfiles&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The editor war
&lt;/h2&gt;

&lt;p&gt;When Unix culture became popularized, the community quickly found itself entertaining fierce discussions. Put a bunch of programmers in a room and they’re bound to disagree about the merits of operating systems, programming languages, version control systems and even indent style. One of these “holy wars” was the rivalry between users of &lt;a href="https://www.gnu.org/software/emacs/" rel="noopener noreferrer"&gt;Emacs&lt;/a&gt; and vi(m), also known as the &lt;a href="https://en.wikipedia.org/wiki/Editor_war" rel="noopener noreferrer"&gt;editor war&lt;/a&gt;, which — according to sources — has been going on at least since 1986!&lt;/p&gt;

&lt;p&gt;Today, this so-called “editor war”, seems far from over. Channels like Reddit, HackerNews or Medium are ripe with people proclaiming (sometimes shouting) which tool is “best” (usually, &lt;em&gt;their&lt;/em&gt; editor or IDE of course!), and I used to be very reluctant to get involved. When I first started working in software development I briefly used &lt;a href="https://www.activestate.com/products/komodo-ide/" rel="noopener noreferrer"&gt;Komodo&lt;/a&gt; and &lt;a href="https://www.spyder-ide.org/" rel="noopener noreferrer"&gt;Spyder&lt;/a&gt;, before joining a company that used &lt;a href="https://www.sublimetext.com/" rel="noopener noreferrer"&gt;SublimeText&lt;/a&gt; and, later on, &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt;. I was happy with all of these tools, and didn’t care for foul-mouthed fanboys of this or that editor &lt;em&gt;du jour&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Recently, however, I have come to appreciate these discussions (if civil, of course) and especially the critical reflection of which tool is best for you. Because, let me be clear from the start, there is no such thing as “the best” editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The right tool for the job
&lt;/h2&gt;

&lt;p&gt;Which editor is best &lt;em&gt;for you&lt;/em&gt;, is a highly personal matter. It depends on a lot of factor, such as personal preference, but also the work you do. A Python developer might prefer &lt;a href="https://www.jetbrains.com/pycharm/" rel="noopener noreferrer"&gt;PyCharm&lt;/a&gt;, because it arguably has the best tooling for Python development. A data scientist will be very comfortable using VSCode, which has excellent integrations for Jupyter Notebooks. A UNIX sysadmin might prefer &lt;a href="https://www.vim.org/" rel="noopener noreferrer"&gt;Vim&lt;/a&gt; because it integrates seamlessly with a terminal workflow like tmux… And sometimes, like on a remote system, your only choice might be to fire up &lt;code&gt;vi&lt;/code&gt;…&lt;/p&gt;

&lt;h2&gt;
  
  
  Only a fool never changes his mind
&lt;/h2&gt;

&lt;p&gt;In other words, the editor or IDE you use should be a deliberate choice based on your development needs and a comparison of the available tools. This means that there are good reasons to at least &lt;em&gt;consider&lt;/em&gt; switching editors once in a while. Just like a carpenter would not use the same tools throughout his career, software development tools constantly evolve. And so do the people who use them (which is why the tools change in the first place). Indeed, only a fool never changes his mind. Moreover, critically reflecting on how your develop and which tools you use can be a great way of introspection and learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enjoy yourself!
&lt;/h2&gt;

&lt;p&gt;When I recently switched &lt;a href="https://tomdeneire.medium.com/vscode-vs-neovim-164cfc7b8399" rel="noopener noreferrer"&gt;from VSCode to Neovim&lt;/a&gt;, there were two main reasons. The first was, without a doubt, personal taste and enjoyment. This reason might seem whimsical or besides the point, but as software developers we spend the majority of our time in our editors, so I think it’s vital this should be a pleasant experience. If you’re working in a boring, frustrating or unattractive environment, it’s bound to have an effect on your disposition, and hence your work. So find something you like and enjoy using. It’s only going to make your work better not only because you’re in a better mental state, but also because you’ll enjoy learning how to get the most out of your tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Being in the driver’s seat
&lt;/h2&gt;

&lt;p&gt;The second reason I prefer my current editor is control. Perhaps I just never understood VSCode as well as I should have, but with Neovim I feel in total control. I understand every bit of the configuration, including the more complicated stuff like language server integration, auto-completion with snippets and syntax coloring. I like that my primary tool only does what I want it to do, only changes what I can fix myself, only shows what I think is important, only updates when I think it is time, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge what you know
&lt;/h2&gt;

&lt;p&gt;Not only am I more in control, I am much more aware of the capabilities of my bread-and-butter tool. I’m sure VSCode or other editors have ways of doing this too, but (Neo)Vim’s powerful (regex) search and replace, repeating the last action (&lt;code&gt;.&lt;/code&gt;), and scriptability (with Lua or just plain &lt;code&gt;:!&lt;/code&gt; shell commands) were game changers for me. You see, if you’ve been using a tool for long enough, you adapt to its capabilities, never realizing that there might be a faster, better way out there. Ironically, this is probably the reason why many people are reluctant to consider changing their editor. What they know, is what they like. However, challenging what you know is an important skill both in life and in software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Think ahead
&lt;/h2&gt;

&lt;p&gt;When I first considered migrating away from my previous setup, I actually thought it would be very hard to accomplish. You see, where I work, we use a set of bespoke file types, each with their own syntax, snippets and workflow, which was fully integrated in my development environment as VSCode extensions. Another vital extension offered a GUI wrapper to a custom CLI tool we use for deployment and version control, which is also indispensable for our work. So before I could use Neovim for work, I had to write my own syntax files and plugins to replace these. Not only was this very easy to accomplish with the builtin Lua interpreter, by doing so I now feel much more independent of my editor. It is never a good idea to be married to a piece of technology. You never know when you’ll want (or be forced) to change it for something else. So, you could say, paradoxically, that moving to Neovim has made it easier for me to move away from Neovim if I wanted to in the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  Smooth like coconut oil
&lt;/h2&gt;

&lt;p&gt;Most editors promote a specific type of workflow. Some integrate seamlessly with testing and debugging environments, others excel at editing and comparing several files side-by-side, possibly with previews for markup like Markdown or reStructuredText. Still others, like Neovim, are really well-suited for hopping between the terminal to the editor and back. Considering your typical development workflow and which editor is best for that, is also a worthwile learning experience. The most important areas you can look at for improvement, are the actions you perform hundreds of times a day. Things like file navigation, running unit tests, refactoring a piece of code, … If you can improve one of those, it’s going to have an enormous effect on your workflow, both saving you time and making your life easier. “You want to be smooth as coconut oil” — as one Netflix engineer and popular &lt;a href="https://www.youtube.com/channel/UC8ENHE5xdFSwx71u3fDH5Xw" rel="noopener noreferrer"&gt;YouTuber&lt;/a&gt; would say …&lt;/p&gt;

&lt;h2&gt;
  
  
  Listen to your body
&lt;/h2&gt;

&lt;p&gt;Something quite akin to development workflow is ergonomics. Again, if you’re going to use a tool for hours on end, you have got to feel physically comfortable with it. For me, being able to use keyboard-based editing, file navigation and version control (I use &lt;a href="https://github.com/jesseduffield/lazygit" rel="noopener noreferrer"&gt;lazygit&lt;/a&gt; for this), had a surprising impact on the neck and shoulder issues I was experiencing when I used the mouse more often. For the record, Neo(Vim) is not the only keyboard-oriented editor out there. If your interested, you should checkout &lt;a href="https://helix-editor.com/" rel="noopener noreferrer"&gt;Helix&lt;/a&gt; and &lt;a href="https://lapce.dev/" rel="noopener noreferrer"&gt;Lapce&lt;/a&gt; too, and of course, Emacs ;-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Know thyself
&lt;/h2&gt;

&lt;p&gt;I hope you will now agree that exploring editors is an exciting experience which will make you a better developer, even if you stay with your current setup. It’s a process of reflection, at the end of which you will have a better understanding of how you work and why you work the way you do! It’s 2023: the time of the editor wars of yore should be over. But in an era where programmers face increasing competition from AI code generation, self-critical reflection is an absolute must.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>editor</category>
      <category>vscode</category>
      <category>neovim</category>
      <category>emacs</category>
    </item>
    <item>
      <title>Battling impostor syndrome as a software engineer</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 25 Feb 2023 14:58:58 +0000</pubDate>
      <link>https://dev.to/tomdeneire/battling-impostor-syndrome-as-a-software-engineer-1kld</link>
      <guid>https://dev.to/tomdeneire/battling-impostor-syndrome-as-a-software-engineer-1kld</guid>
      <description>&lt;h2&gt;
  
  
  Battling impostor syndrome as a software engineer
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6886%2F0%2Ab4mZQzaEuErYaqu5" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6886%2F0%2Ab4mZQzaEuErYaqu5" alt="Photo by [Matheus Farias](https://unsplash.com/@karmatheux?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="760" height="1139"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://unsplash.com/@karmatheux?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Photo by Matheus Farias&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Impostor syndrome
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Impostor_syndrome" rel="noopener noreferrer"&gt;Impostor syndrome&lt;/a&gt; or “impostorism” is a psychological phenomenon in which an individual doubts their skills, talents, or accomplishments and has a persistent internalized fear of being exposed as a fraud. Despite external evidence of their competence, people experiencing impostorism do not believe they deserve their success or luck.&lt;/p&gt;

&lt;p&gt;It has been &lt;a href="https://www.theopennotebook.com/2016/11/15/feeling-like-a-fraud-the-impostor-phenomenon-in-science-writing/" rel="noopener noreferrer"&gt;estimated&lt;/a&gt; that nearly 70% of us will experience symptoms of impostor phenomenon at least once in our lives. It is spread equally among men and women and occurs in various settings, such as a new living environment, academia, social interactions and relationships, and — perhaps most of all — the workplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impostorism in IT
&lt;/h2&gt;

&lt;p&gt;In my experience, impostor syndrome is exceptionally present in IT. Almost all of the people I have worked with — engineers, analysts and designers alike — have at one time confessed feelings of being a fraud or a fake, or of feeling inadequate for their jobs.&lt;/p&gt;

&lt;p&gt;This is only logical because of the nature of the IT sector.&lt;/p&gt;

&lt;p&gt;For one, it actively promotes &lt;strong&gt;perfectionism&lt;/strong&gt;. In software, things are either right or wrong — hence the culture of testing. This is, of course, excellent development practice, but with insecure people, you can see how it may stimulate fear of failure. Ask yourself, for instance, would you go to sleep easily on a day your tests keep failing and you don’t know why?&lt;/p&gt;

&lt;p&gt;Secondly, the IT business is full of &lt;strong&gt;very intelligent people&lt;/strong&gt;. Some experience this as a privilege or a stimulating work environment, but it can also lead people to compare themselves to the (perceived) standards of others. For instance, when your colleagues have computer science degrees and you are perhaps self-taught.&lt;/p&gt;

&lt;p&gt;Thirdly, when things go wrong in IT — which they inevitably do sometimes — it is often very ease to put the &lt;strong&gt;blame&lt;/strong&gt; on someone. While some companies are already actively promoting a zero-blame culture, others still analyse issues in terms of &lt;em&gt;who messed up here?&lt;/em&gt; This mindset is even engrained in our tools. Just think of the psychology behind a command like git blame !&lt;/p&gt;

&lt;p&gt;Finally, IT is a &lt;strong&gt;fast-paced&lt;/strong&gt; work environment with lots of people coming and going. I know people who have walked away from great jobs because of impostor syndrome, only to end up in the same situation with the next job. And with the recent wave of lay-offs in the sector, I can only imagine what getting fired would do for someone who is already feeling like an impostor…&lt;/p&gt;

&lt;h2&gt;
  
  
  Fear of failure
&lt;/h2&gt;

&lt;p&gt;Impostor syndrome is not recognized by “official” manuals like the &lt;a href="https://en.wikipedia.org/wiki/Diagnostic_and_Statistical_Manual_of_Mental_Disorders" rel="noopener noreferrer"&gt;DSM&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/International_Statistical_Classification_of_Diseases_and_Related_Health_Problems" rel="noopener noreferrer"&gt;ICD&lt;/a&gt;, and that’s fine by me. Impostorism is nothing but a particular example of a much more fundamental aspect of human emotion: &lt;em&gt;fear&lt;/em&gt;. There are three basic forms of fear: fear of &lt;strong&gt;change&lt;/strong&gt; (or &lt;strong&gt;death&lt;/strong&gt;), fear of &lt;strong&gt;abandonment&lt;/strong&gt; and fear of &lt;strong&gt;failure (&lt;/strong&gt;the latter two being closely related).&lt;/p&gt;

&lt;p&gt;With impostor syndrome, it’s obviously fear of failure, and fear of being abandoned because of that failure, that is underneath. This is perhaps the most &lt;em&gt;human&lt;/em&gt; form of fear. You won’t see a tiger doubting its ability to climb a tree or a hawk in disbelief that it can soar the skies. Animals know their capabilities and rely on them. People are afraid to fail, even if they know their capabilities.&lt;/p&gt;

&lt;p&gt;Another typically human trait that is related to and exacerbates this fear of failure, is what is our so-called &lt;strong&gt;inner storyteller&lt;/strong&gt;. I’m talking about your inner monologue and how it can quickly turn towards the negative. Imagine you are about to deploy an important new feature and observe your train of thought. Are you excited about the customer feedback or are you dreading their response? How will your team lead react? Are you proud to show them your work or are you already thinking of potential flaws in your code? What will your colleagues say? Will they applaud your technical choices or are you already anticipation that one person who is always critical?&lt;/p&gt;

&lt;h2&gt;
  
  
  What can I do about it?
&lt;/h2&gt;

&lt;p&gt;In all of the above, it is important to acknowledge that a small degree of fear of failure is natural. Anticipating problems (storytelling) and thinking twice before doing something (fear of failure) are indeed human traits, which can be beneficial if they lead to self-preservation or self-improvement. That’s why tigers sometimes fall from trees, while people use ropes when they go climbing…&lt;/p&gt;

&lt;p&gt;With impostor syndrome, though, we are far from such “ecological” or normal fear. This is Fear with a capital F — crushing, debilitating fear, spells of anxiety, panic attacks, sleeplessness, heart palpitations, headaches, and so on. Symptoms you can’t handle by taking a scented bath or getting a massage, or indulging in a crazy night out with friends (although this is the stuff people try).&lt;/p&gt;

&lt;p&gt;So what can you do about it? There are different strategies to handle impostor syndrome and while not all of them are as effective, you still need all of them to succeed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try this (but it’s not enough)
&lt;/h3&gt;

&lt;p&gt;The first stage is &lt;strong&gt;mental&lt;/strong&gt;. While many people with impostor syndrome know their capabilities, many are also truly convinced they do not have what it takes. So, be honest, how do you view yourself? Do you really believe in your skills and talents? Are you able to tell a co-worker or your boss that you’re good at your job? If you’re not, you need to work on your mindset and confidence. One concrete thing you can try, is writing up your CV. I have found it can help you realize your true potential and experience. In the vast world of software engineering it’s often easier to see what you &lt;em&gt;can’t do&lt;/em&gt; than what can and have already done.&lt;/p&gt;

&lt;h3&gt;
  
  
  This helps (but it’s not easy)
&lt;/h3&gt;

&lt;p&gt;The mental stage is only the tip of the iceberg, though. What you believe, is good start, but it is nowhere near enough. It’s what you feel, the &lt;strong&gt;emotional&lt;/strong&gt; part, that counts. As said, many people know full well that they are competent engineers, but they still &lt;em&gt;feel&lt;/em&gt; like an impostor! That’s why it’s vital to not only know what you’re worth with your head, but also with your gut. And that’s more than just a metaphor. As always with emotion, the answer is in your body. Think of a child being afraid in the dark. You can’t really convince it that there are no monsters under the bed. You can even go look, and it will still be afraid. But a warm hug, a soft reassuring voice and a night lamp will help. That’s because these things trigger a &lt;em&gt;physical&lt;/em&gt; response, not a mental one, and fear is a physical phenomenon. So as an adult, you are emotionally responsible to help yourself turn this fear into self-love, and you can’t do this with your head.&lt;/p&gt;

&lt;h3&gt;
  
  
  This works (but it takes time)
&lt;/h3&gt;

&lt;p&gt;Clearing out the fear of failure from your body is not easy. And even if you succeed in getting rid of the negative emotions when they occur, this is still not a permanent solution. The only thing that will really change impostor syndrome is a &lt;strong&gt;therapeutical&lt;/strong&gt; approach. It takes a skilled therapist to help you recognize and manage the physical feelings of stress and anxiety, and to help you work on what lies beneath your fear of failure. Really dealing with impostor syndrome means opening up that can of worms that will take you to your absent dad, your hypercritical mom, your overachieving brother, your manipulative friend, your demeaning teacher, your failed driver’s test, …&lt;/p&gt;

&lt;h2&gt;
  
  
  It gets better
&lt;/h2&gt;

&lt;p&gt;Of course, the last step is the most difficult one. Many people are afraid (again, fear of failure!) to take it, because they think that if they open up, things will get worse instead of better. And the truth is, they might, but only in the very short run.&lt;/p&gt;

&lt;p&gt;When I was battling my own demons, my tech lead at the time once said that he believed that if someone was absent for mental reasons, they would never return to their previous level. At the time, this worried me, as I looked up to him and was afraid he might be right. Now, I know different.&lt;/p&gt;

&lt;p&gt;Therapy has made me a much stronger person and, therefore, a much more capable software engineer. But it’s true, there are no shortcuts. It’s going to take time and it’s going to hurt.&lt;/p&gt;

&lt;p&gt;But you can do it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you want to know more about the psycho-therapeutical approach behind this blog, developed by psychiatrist dr. Tom Herregodts, check out his YouTube video&lt;/em&gt; &lt;a href="https://www.youtube.com/watch?v=JXeIYrI8d2k" rel="noopener noreferrer"&gt;Physics of fear&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>impostorsyndrome</category>
      <category>mentalhealth</category>
      <category>software</category>
      <category>selfimprovement</category>
    </item>
    <item>
      <title>Text versus bytes</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 09:24:34 +0000</pubDate>
      <link>https://dev.to/tomdeneire/text-versus-bytes-2g3k</link>
      <guid>https://dev.to/tomdeneire/text-versus-bytes-2g3k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AiHISfT_t3GUTJEE6WFkn2g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AiHISfT_t3GUTJEE6WFkn2g.jpeg" alt="Photo by [Hope House Press — Leather Diary Studio](https://unsplash.com/@hope_house_press_leather_diary_studio?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/binary?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="640" height="853"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@hope_house_press_leather_diary_studio?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Hope House Press — Leather Diary Studio&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/binary?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TL;DR: There is no such thing as &lt;em&gt;text&lt;/em&gt;, only collections of &lt;em&gt;bytes&lt;/em&gt; which can be displayed as &lt;em&gt;characters *based on an *encoding&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ones and zeros
&lt;/h2&gt;

&lt;p&gt;A computer is an electronic device, which really only "understands" on and off. Think of how the light goes on and off when you flip the switch. In a way, a computer is basically a giant collection of light switches.&lt;/p&gt;

&lt;p&gt;This is why a computer's processor can only operate on &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;, or &lt;strong&gt;bits&lt;/strong&gt;, which can be combined to represent binary numbers, e.g. &lt;code&gt;100 = 4&lt;/code&gt;. It is these binary numbers that the processor uses as both data and instructions (a.k.a. "machine code").&lt;/p&gt;

&lt;p&gt;It makes sense to group bits into units; otherwise, we would just end up with one long string of ones and zeros and no way to chop it up into meaningful parts. A group of eight binary digits is called a &lt;strong&gt;byte&lt;/strong&gt;, but historically the size of the byte is not strictly defined. In general, though, modern computer architectures work with an 8-bit byte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bytes
&lt;/h2&gt;

&lt;p&gt;This binary nature of computers means that on a fundamental level all data is just a collection of bytes. Take files, for instance. In essence, there's no difference between a text file, an image or an executable. So it's actually a bit (pun not intended) confusing when people talk about the "binary" files, i.e. not human-readable, as opposed to human-readable "text".&lt;/p&gt;

&lt;p&gt;Let's look at an example &lt;code&gt;myfile&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ xxd -b myfile
00000000: 01101000 01100101 01101100 01101100 01101111 00100000
00000006: 01110111 01101111 01110010 01101100 01100100 00001010
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The instruction &lt;code&gt;xxd -b&lt;/code&gt; asks for a binary "dump" of &lt;code&gt;myfile&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We see that it contains 12 eight-bit bytes. Because the binary representation is difficult on the eyes, bytes are often displayed as hexadecimal numbers:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ xxd -g 1 myfile
00000000: 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or (less often) as decimal numbers:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ od -t d1 myfile
0000000  104  101  108  108  111   32  119  111  114  108  100  10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In decimals, 8-bit bytes go up to 256, which makes sense as 2⁸ = 256, i.e. eight positions can hold either zero or one, which equals 256 combinations.&lt;/p&gt;

&lt;p&gt;But how do we know what these bytes represent?&lt;/p&gt;

&lt;h2&gt;
  
  
  Character encoding
&lt;/h2&gt;

&lt;p&gt;In order to interpret bytes in an meaningful way, for instance to display them as text or as an image, we need to give the computer additional information. This is done in several ways, one of which is predetermining the file structure with identifiable sequences of bytes.&lt;/p&gt;

&lt;p&gt;Another is specifying an &lt;strong&gt;encoding&lt;/strong&gt;, which you can think of as a lookup table connecting meaning to its corresponding digital representation. When it comes to text, we call this "character&lt;br&gt;
encoding". Turning characters into code is referred to as "encoding", interpreting code as characters is "decoding".&lt;/p&gt;

&lt;p&gt;One of the earliest character encoding standards was &lt;a href="https://en.wikipedia.org/wiki/ASCII" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt;, which specifies that the character &lt;code&gt;a&lt;/code&gt; is represented as byte &lt;code&gt;61&lt;/code&gt; (hexadecimal) or &lt;code&gt;97&lt;/code&gt; (decimal) or &lt;code&gt;01100001&lt;/code&gt; (binary). However, since 8-bit bytes only give you 256 possibilities, today multibyte encodings are used. In the past, different areas of the world used different encodings, which was software's Tower of Babel, causing a bunch of communication problems to this day. Luckily, today &lt;a href="https://en.wikipedia.org/wiki/UTF-8" rel="noopener noreferrer"&gt;UTF8&lt;/a&gt; is more or less the international standard --- for instance, accounting for 97% of all web pages. UTF-8 is capable of encoding all 1,112,064 valid character &lt;a href="https://en.wikipedia.org/wiki/Code_point" rel="noopener noreferrer"&gt;code points&lt;/a&gt; in &lt;a href="https://en.wikipedia.org/wiki/Unicode" rel="noopener noreferrer"&gt;Unicode&lt;/a&gt; using one to four one-byte units.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bytes as text
&lt;/h2&gt;

&lt;p&gt;Going back to our file, we can now ask the computer to interpret these bytes as text. It is important to realize that any time we display bytes as text, be it in a terminal, a word processor, an editor or a browser, we need a character encoding. Often, we are unaware of encoding that is used, but there is always a choice to be made, whether by default settings or by some clever software that tries to identify the encoding.&lt;/p&gt;

&lt;p&gt;Terminals, for instance, have a default character setting --- mine is set to UTF-8. So when we ask to print &lt;code&gt;myfile&lt;/code&gt; we see this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat myfile
hello world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This means the bytes we discussed earlier are the UTF-8 representation of the string &lt;code&gt;hello world&lt;/code&gt;. For this example, other character encodings, like ASCII or ISO-Latin-1 would yield the same result. But the difference quickly becomes clear when we look at another example.&lt;/p&gt;

&lt;p&gt;Let's save the UTF-8 encoded text string &lt;code&gt;El Niño&lt;/code&gt; as a file and then print it. We can do that in the terminal --- remember, it's set to UTF-8 display by default:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ echo "El Niño" &amp;gt; myfile
$ cat myfile
El Niño
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let's change the terminal's encoding to &lt;a href="https://en.wikipedia.org/wiki/Windows-1252" rel="noopener noreferrer"&gt;CP-1252&lt;/a&gt; and see what happens when we print the same file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat myfile
El NiÃ±o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We call this &lt;a href="https://en.wikipedia.org/wiki/Mojibake" rel="noopener noreferrer"&gt;Mojibake&lt;/a&gt;; the garbled text that I'm sure you've often seen under the form of the generic replacement �. But do you understand why this happens? Because &lt;code&gt;myfile&lt;/code&gt; contains bytes entered as UTF-8 encoded text, displaying the same bytes in another encoding doesn't give the result we expect.&lt;/p&gt;

&lt;p&gt;This is also explains why commands like &lt;code&gt;cat&lt;/code&gt; don't work on so-called binary files, or opening them in an editor reveals only gibberish: they're not encoded as text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Text as bytes
&lt;/h2&gt;

&lt;p&gt;The example of &lt;code&gt;El Niño&lt;/code&gt; shows that we can also take text --- a string typed in a terminal --- and use that as bytes. For instance, when we save text from an editor in a file. At first, this can be a tricky concept to wrap your head round. Bytes can be strings and strings are bytes. The important thing to remember is that whenever you handle text or characters, there is an (explicit or implicit) encoding at work.&lt;/p&gt;

&lt;p&gt;When you think of it, code is text too, so some programming languages make certain encoding assumptions as well. Others just deal with text as bytes and leave the encoding up to other applications (such as a browser or a terminal).&lt;/p&gt;

&lt;p&gt;Go, for instance, is natively UTF-8, for instance, which means you can do this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python 3 is UTF-8 too, but Python 2 used to be ASCII. So, regardless of whether your code editor is able to display such a string or not, the Python 2 will complain if you try to use the print function on it. Remember, print tells a device to display bytes. So if you put this in a file &lt;code&gt;test.py&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print "Hello, 世界"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and execute it with Python 2, it will throw the following error.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;py2 test.py

File "test.py", line 1
SyntaxError: Non-ASCII character '\\xe4' in file test.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The bottom line is that you should always be careful when handling text and when in doubt use explicit encoding or decoding mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling multibyte characters
&lt;/h2&gt;

&lt;p&gt;There’s a lot more to say about character encodings, but I’ll wrap things up with an observation about multibyte characters that might prompt you to study the subject more in depth.&lt;/p&gt;

&lt;p&gt;A popular question in code interviews is to ask the candidate to write (pseudo-)code to reverse a string. In Python, for instance, there is a nice oneliner for this, which uses a slice from end to start (&lt;code&gt;::&lt;/code&gt;) that steps backward (&lt;code&gt;-1&lt;/code&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print("Hello World"[::-1])
dlroW olleH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Yet think about what happens under the hood. Apparently, there is a mechanism that iterates over the bytes that make up the string and reverses their order. But what happens when a character is represented by more than one byte? For instance, 界 , is four bytes in UTF-8 (&lt;code&gt;e7 95 8c 0a&lt;/code&gt; in hex). The first of these is a &lt;em&gt;leader&lt;/em&gt; byte, a byte reserved to start a specific multibyte sequence, the other three are &lt;em&gt;continuation&lt;/em&gt; bytes, which are only valid when preceded by a leader. So when you reverse these bytes, you end up with a different byte sequence, which is actually invalid UTF-8!&lt;/p&gt;

&lt;p&gt;Fortunately, Python (which is natively UTF-8, remember) is able to handle this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print("Hello, 世界"[::-1])
界世 ,olleH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In other programming languages, though, you would have to write a function that identifies byte &lt;em&gt;units&lt;/em&gt; in the string and then reverse their order, not the bytes themselves. Which would imply knowledge of the string’s encoding…&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Text versus bytes is a complex issue that even advanced programmers can struggle with, or have tried to avoid for most of their careers. However, it is a fascinating reminder of the very essence of computing and understanding it, or at least the fundamentals, is really indispensable for any software developer.&lt;/p&gt;

&lt;p&gt;If you’re looking for another source to read up on the matter, you can start with &lt;a href="https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/" rel="noopener noreferrer"&gt;The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)&lt;/a&gt; by &lt;a href="https://www.joelonsoftware.com/about-me/" rel="noopener noreferrer"&gt;Joel Spolsky&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>text</category>
      <category>bytes</category>
      <category>linux</category>
      <category>encoding</category>
    </item>
    <item>
      <title>TIL: wrapping my head around Go’s “iota”</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 09:15:45 +0000</pubDate>
      <link>https://dev.to/tomdeneire/til-wrapping-my-head-around-gos-iota-33h2</link>
      <guid>https://dev.to/tomdeneire/til-wrapping-my-head-around-gos-iota-33h2</guid>
      <description>&lt;p&gt;&lt;em&gt;TIL (“Today I learned”) are shorter, less-researched posts that I typically write to help organize my thoughts and solidify things I have learned while working. I post them here as a personal archive and of course for others to possibly benefit from.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6000%2F0%2ASj-lxNZK6u3b7G2x" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6000%2F0%2ASj-lxNZK6u3b7G2x" alt="Photo by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="529"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@kellysikkema?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Iota
&lt;/h2&gt;

&lt;p&gt;A few days ago, I happened upon the &lt;code&gt;iota&lt;/code&gt; identifier in Go.&lt;/p&gt;

&lt;p&gt;I remembered seeing it before, but it’s still pretty rare, so I looked up the definition of &lt;code&gt;iota&lt;/code&gt; in the &lt;a href="https://pkg.go.dev/builtin#pkg-constants" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const iota = 0 // Untyped int.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;iota is a predeclared identifier representing the untyped integer ordinal number of the current const specification in a (usually parenthesized) const declaration. It is zero-indexed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ¿Qué?
&lt;/h2&gt;

&lt;p&gt;Upon reading this (several times over actually) I must confess I still didn’t really understand what &lt;code&gt;iota&lt;/code&gt; was or did. And while the &lt;a href="https://go.dev/ref/spec#Iota" rel="noopener noreferrer"&gt;language specification&lt;/a&gt; is more explicit and has examples, it is not much clearer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. Its value is the index of the respective ConstSpec in that constant declaration, starting at zero. It can be used to construct a set of related constants&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some additional browsing, in &lt;a href="https://golangbyexample.com/iota-in-golang/" rel="noopener noreferrer"&gt;Golang by Example&lt;/a&gt;, for instance, reveals that &lt;code&gt;iota&lt;/code&gt; can be used to implement enums in Go. Like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Size uint8

const (
    small Size = iota
    medium
    large
    extraLarge
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;which is effectively the same as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Size uint8

const (
 small      Size = 0
 medium     Size = 1
 large      Size = 2
 extraLarge Size = 3
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and, indeed, a cleaner solution than defining &lt;code&gt;Size&lt;/code&gt; like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Size string

const (
 small      Size = "small"
 medium     Size = "medium"
 large      Size = "large"
 extraLarge Size = "extraLarge"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  The power of a great example
&lt;/h2&gt;

&lt;p&gt;Even after these examples, I didn’t really see much benefit in &lt;code&gt;iota&lt;/code&gt;, apart from its auto-increment function.&lt;/p&gt;

&lt;p&gt;It was only when I read the example from &lt;a href="https://go.dev/doc/effective_go" rel="noopener noreferrer"&gt;Effective Go&lt;/a&gt;, that I realised the true power of &lt;code&gt;iota&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type ByteSize float64

const (
    _           = iota // ignore first value by assigning to blank identifier
    KB ByteSize = 1 &amp;lt;&amp;lt; (10 * iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

func (b ByteSize) String() string {
    switch {
    case b &amp;gt;= YB:
        return fmt.Sprintf("%.2fYB", b/YB)
    case b &amp;gt;= ZB:
        return fmt.Sprintf("%.2fZB", b/ZB)
    case b &amp;gt;= EB:
        return fmt.Sprintf("%.2fEB", b/EB)
    case b &amp;gt;= PB:
        return fmt.Sprintf("%.2fPB", b/PB)
    case b &amp;gt;= TB:
        return fmt.Sprintf("%.2fTB", b/TB)
    case b &amp;gt;= GB:
        return fmt.Sprintf("%.2fGB", b/GB)
    case b &amp;gt;= MB:
        return fmt.Sprintf("%.2fMB", b/MB)
    case b &amp;gt;= KB:
        return fmt.Sprintf("%.2fKB", b/KB)
    }
    return fmt.Sprintf("%.2fB", b)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You use iota to define constants, but that doesn’t mean the constant cannot apply arithmetic to an &lt;code&gt;iota&lt;/code&gt;. So, through clever use of the bitwise shift operator &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;, you can make iota do the heavy lifting for you in defining byte units!&lt;/p&gt;

&lt;p&gt;What a great example to explain the concrete usage of an abstract notion! I only wish examples like this would be included in the official documentation instead of a document that describes itself as “tips for writing clear, idiomatic Go code”…&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>iota</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>VSCode vs Neovim</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 09:12:17 +0000</pubDate>
      <link>https://dev.to/tomdeneire/vscode-vs-neovim-1i89</link>
      <guid>https://dev.to/tomdeneire/vscode-vs-neovim-1i89</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8544%2F0%2AEJ0hkZMdn-4QB1Yf" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8544%2F0%2AEJ0hkZMdn-4QB1Yf" alt="Photo by [Christopher Robin Ebbinghaus](https://unsplash.com/@cebbinghaus?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@cebbinghaus?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Christopher Robin Ebbinghaus&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tomdeneire.medium.com/til-vim-motions-49ef8ca8f064" rel="noopener noreferrer"&gt;A while ago&lt;/a&gt; I wrote about the fact that I was using Vim motions in VSCode and that I was exploring &lt;a href="http://neovim.io/" rel="noopener noreferrer"&gt;Neovim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since then, I have really fallen in love with Neovim (although sometimes it was more of a love-hate relationship ;-) ) and I use it full-time now. In this post I want to explain why and critically compare my experiences with both tools.&lt;/p&gt;

&lt;p&gt;(Before we start, just a quick word about Neovim vs Vim. I guess most of my observations will hold true for regular Vim as well, although there are some things that make Neovim a superior product, such as its builtin LSP (language server protocol) client, builtin terminal emulator, and embedding of the Lua programming language.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and setup
&lt;/h2&gt;

&lt;p&gt;Proponents of VSCode will say that it’s much easier to install and setup, while proponents of Neovim will say that if you want to do VSCode right and if you know what you are doing in Neovim, there is really not much difference.&lt;/p&gt;

&lt;p&gt;When I started with Neovim I was a complete newbie (still am, really), so I would have to agree that setting up Neovim is &lt;strong&gt;time-consuming&lt;/strong&gt; and comes with a learning curve. LSP might be built in, but installing the language servers or getting autoformatting and autocompletion to work was not trivial. However, now that I’ve done it, it would be really easy to (re)do a vanilla install, because the setup is very &lt;strong&gt;portable&lt;/strong&gt;. I’ve put my .dotfiles in a Git repository and that’s really all you need. Granted, VSCode does have a settings.json(which you can sync to GitHub, if I’m not mistaken), but it doesn’t hold nearly as much information as Neovim’s configuration files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance / UX
&lt;/h2&gt;

&lt;p&gt;As far as performance and user experience go, Neovim is the clear winner. It is &lt;strong&gt;really fast&lt;/strong&gt; starting up, there is almost no lag, the application will not ask to you to reinstall plugins, and so on.&lt;/p&gt;

&lt;p&gt;The editing itself also feels very snappy and responsive when typing or opening other files. Faster &lt;strong&gt;navigation&lt;/strong&gt; between files and tabs is a clear win for me. Of course this partly due to the extensive use of mappings, but then again even with the best keybindings I don’t think you could get VSCode to do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensions / plugins
&lt;/h2&gt;

&lt;p&gt;There is no doubt that the VSCode/Typescript &lt;strong&gt;ecosystem&lt;/strong&gt; for extensions is larger than the counterpart for (Neo)Vim/Vimscript/Lua plugins. One simple thing I miss, for instance, is a good (working) rainbow tags plugin. Another, more important perhaps, is Git integration, although to be fair, I haven’t explored the (Neo-)Vim options too much for that.&lt;/p&gt;

&lt;p&gt;Moreover, VSCode, being Electron, i.e. &lt;strong&gt;browser software&lt;/strong&gt;, can do things like Jupyter Notebooks, markdown rendering, which are perhaps not impossible in Neovim, but certainly more difficult to achieve. Of course, you ask the question whether you really want an editor to do that instead of using dedicated applications for that.&lt;/p&gt;

&lt;p&gt;On the other hand, Neovim plugins are amazingly &lt;strong&gt;customizable&lt;/strong&gt;. For instance, you can write Lua functions that have your statusline display exactly what you want it to say, or parametrize fuzzy file searching to your specific needs. This might seem like a small thing, but haven’t you ever wanted a certain extension to do you it slightly different so that it would be &lt;em&gt;perfect for you&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Moreover, Neovim plugin development is much better than the VSCode counterpart, which involves installing a ton of software and a rather complicated build process.&lt;/p&gt;

&lt;p&gt;Overall, Neovim is, as advertised, truly &lt;strong&gt;hyperextensible&lt;/strong&gt;, it’s integrated Vimscript and Lua make it easy to get your editor to do more advanced things, like custom syntax colouring (at work, we work with quite a few bespoke filetypes), or just write a function to map a keystroke to an elaborate command or a Shell script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comfort
&lt;/h2&gt;

&lt;p&gt;I first started using Vim motions because I was curious and because I have been struggling with a bad back and neck pain. Honestly, I didn’t think switching to Vim motions would have much of an impact, but in fact, I feel a clear difference. Of course, regular sittings breaks, good posture, and such are equally import, but I do feel that working with Vim motions is more &lt;strong&gt;ergonomic&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aesthetics
&lt;/h2&gt;

&lt;p&gt;This sort of depends on your &lt;strong&gt;personal preference&lt;/strong&gt;, but to me, it’s a bit of a tie. You can make Neovim look really nice with &lt;a href="https://www.nerdfonts.com/" rel="noopener noreferrer"&gt;patched fonts&lt;/a&gt; and it’s great you can git rid of all the clutter. On the other hand, you still feel in a terminal-based editor. (Which is not necessarily a bad thing). You can compare these two screenshots of the same file (with LSP diagnostics at work):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugovumb8zqc5i2zrs1by.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugovumb8zqc5i2zrs1by.png" alt="A Go file in my VSCode setup" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxvevsarawfzvv8ofufv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxvevsarawfzvv8ofufv.png" alt="The same Go file in my Neovim setup" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So, is Neovim worth it?&lt;/p&gt;

&lt;p&gt;If you’re trying to answer this question for yourself, I would recommend watching &lt;a href="https://www.youtube.com/watch?v=rNsWTWvm8uw" rel="noopener noreferrer"&gt;“Does your editor matter?”&lt;/a&gt; by Primeagen on YouTube. I agree 100% that the important things is getting to know your editor and maximizing its potential to help your development process. Whether its VSCode, Neovim or anything else, get to know your tool!&lt;/p&gt;

&lt;p&gt;I personally wouldn’t recommend Neovim for a starting developer, but for me, at this stage of my software engineering career, it’s clearly a superior tool.&lt;/p&gt;

&lt;p&gt;(Disclaimer: you might find Neovim addictive! I’m not kidding, for the first few weeks I was in a real frenzy trying to get everything working and then to customize it exactly to my liking!)&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>neovim</category>
      <category>editor</category>
    </item>
    <item>
      <title>Handling Common Data Formats in Go (TXT)</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 09:08:09 +0000</pubDate>
      <link>https://dev.to/tomdeneire/handling-common-data-formats-in-go-txt-36c4</link>
      <guid>https://dev.to/tomdeneire/handling-common-data-formats-in-go-txt-36c4</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6912%2F0%2A_DXR9Q7SiQLQNqhW" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F6912%2F0%2A_DXR9Q7SiQLQNqhW" alt="Photo by [Alina Grubnyak](https://unsplash.com/@alinnnaaaa?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@alinnnaaaa?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Alina Grubnyak&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Reading and writing data is one of the basic elements of programming. In Go, which is a compiled language with strong typing, this might seem somewhat more complicated than other languages like Python. Here’s how to handle the most common data formats like a true Gopher…&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Text
&lt;/h2&gt;

&lt;p&gt;“Data” does not necessarily have to be &lt;em&gt;structured&lt;/em&gt; data. A plain &lt;code&gt;.txt&lt;/code&gt; file (or any file format really) can be a legitimate source of data. Although opening a file and reading its contents may seem like a trivial enough task, there are still several ways to do this in Go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading a whole file
&lt;/h3&gt;

&lt;p&gt;One way is to read a complete file into memory, so this is only an option when you know a file is going to be limited in size (like configuration files and such).&lt;/p&gt;

&lt;p&gt;The canonical way to do this, is to use &lt;code&gt;os.ReadFile&lt;/code&gt; (before Go 1.16 there was also &lt;code&gt;ioutil.ReadFile&lt;/code&gt;, which is now deprecated)&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Output:

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello
world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Reading a file bit by bit
&lt;/h3&gt;

&lt;p&gt;When dealing with larger files, it is better to read them bit by bit, either as a limited number of bytes, or line by line, or even (in the case of text) word by word.&lt;/p&gt;

&lt;p&gt;All of these options involve opening the file with &lt;code&gt;os.Open&lt;/code&gt; and making sure it also gets closed. (In the previous example, &lt;code&gt;os.ReadFile&lt;/code&gt; took care of that on its own). In Go, we do that using the &lt;a href="https://go.dev/ref/spec#Defer_statements" rel="noopener noreferrer"&gt;defer&lt;/a&gt; keyword, which guarantees the execution of a function after the surrounding function ends, even if it panics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Byte chunks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first method first declares a bytes buffer of 4 bytes. It then reads the file in 4 byte chunks at a time until it reaches the end of the file, which is signaled by the &lt;code&gt;Read()&lt;/code&gt; method by returning a specific error, namely &lt;code&gt;io.EOF&lt;/code&gt; (end of file):&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hell = 4 bytes
o
wo = 4 bytes
rldo = 3 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As you can see, this is not really optimal for handling text, as obviously the byte chunks split up words arbitrarily. To counter that, Go has several handy functions in the &lt;a href="https://pkg.go.dev/bufio" rel="noopener noreferrer"&gt;bufio&lt;/a&gt; package (which is dedicated to &lt;em&gt;buffered&lt;/em&gt; I/O, as in the previous example) that allow more text-oriented buffering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Line by line&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bufio package uses a special type for these operations, called a &lt;code&gt;scanner&lt;/code&gt;. This type comes with a &lt;code&gt;Scan()&lt;/code&gt; method, which allows to step through the ‘tokens’ of the input. The specification of a token is defined by a split function. Scanning stops when an error is encountered and only returns that error when the &lt;code&gt;Errmethod&lt;/code&gt; is called.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello
world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Word by word&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scanning line by line is actually the default split for a scanner, so we could just leave out the line&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scanner.Split(bufio.ScanLines)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If we want to user another splitter, like word by word, we can simply replace said line with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scanner.Split(bufio.ScanWords)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Other input sources
&lt;/h2&gt;

&lt;p&gt;In the above, we have been reading text from a file, but you can also apply the same techniques with different input sources. Reading in general is most often done in Go through the use of an &lt;code&gt;io.Reader&lt;/code&gt;, which is an interface that wraps the basic &lt;code&gt;Read&lt;/code&gt; method, meaning that it will accept any type that implements the Read method. As &lt;code&gt;bufio.NewScanner&lt;/code&gt; takes an &lt;code&gt;io.Reader&lt;/code&gt; as input, we can use all kinds of input sources.&lt;/p&gt;

&lt;p&gt;For instance, you can read from standard input &lt;code&gt;os.Stdin&lt;/code&gt; (which is also an &lt;code&gt;io.Reader&lt;/code&gt;) like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scanner := bufio.NewScanner(os.Stdin)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or you can create an &lt;code&gt;io.Reader&lt;/code&gt; from another variable, e.g. a string:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input := "Hello world"
scanner := bufio.NewScanner(strings.NewReader(input))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or bytes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input := []byte("Hello world")
scanner := bufio.NewScanner(bytes.NewReader(input))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You will now understand that &lt;code&gt;os.Open&lt;/code&gt;, which we discussed earlier, also returns an &lt;code&gt;io.Reader&lt;/code&gt; (or similar types, i.e. that offer a &lt;code&gt;Read&lt;/code&gt; method). And so do other I/O devices in Go, like a network connections or pipes.&lt;/p&gt;

&lt;p&gt;In other words, these readers are everywhere in Go, so it is important to know how to handle them well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stay tuned for the rest of this mini-series which will discuss TXT, CSV, JSON, XML and SQLite!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>txt</category>
      <category>data</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>TIL: Go typecasting with empty interfaces</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 09:02:52 +0000</pubDate>
      <link>https://dev.to/tomdeneire/til-go-typecasting-with-empty-interfaces-3kdo</link>
      <guid>https://dev.to/tomdeneire/til-go-typecasting-with-empty-interfaces-3kdo</guid>
      <description>&lt;p&gt;&lt;em&gt;TIL (“Today I learned”) are shorter, less-researched posts that I typically write to help organize my thoughts and solidify things I have learned while working. I post them here as a personal archive and of course for others to possibly benefit from.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8576%2F0%2AfxM2oKsDOYGnRNp2" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8576%2F0%2AfxM2oKsDOYGnRNp2" alt="Photo by [Suzanne D. Williams](https://unsplash.com/@scw1217?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="531"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@scw1217?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Suzanne D. Williams&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Empty interfaces
&lt;/h2&gt;

&lt;p&gt;Today I was working with &lt;a href="https://pkg.go.dev/github.com/mna/pigeon" rel="noopener noreferrer"&gt;Pigeon&lt;/a&gt;, a Go package which creates parsers based on a &lt;a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar" rel="noopener noreferrer"&gt;parsing expression grammar (PEG)&lt;/a&gt;. As the &lt;a href="https://pkg.go.dev/github.com/mna/pigeon#hdr-Labeled_expression" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; details, it is possible to use a labeled expression in the definition of the rules, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LabeledExpr = value:[a-z]+ {
    fmt.Println(value)
    return value, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the Go code between brackets value is typed as an empty interface (&lt;code&gt;interface{}&lt;/code&gt;). When you match a sequence (as in the above with &lt;code&gt;+&lt;/code&gt; ), the underlying type is a slice of empty interfaces.&lt;/p&gt;

&lt;p&gt;Since an interface is just a set of methods — an empty interface having no methods — , you need to cast these empty interfaces to concrete types (syntax = &lt;code&gt;interface.(type)&lt;/code&gt;) in order to access the underlying values.&lt;/p&gt;

&lt;p&gt;Let’s illustrate this with some code. First, I define a function — for didactic purposes — that will turn any type into an empty interface.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func makeInterface(object interface{}) interface{} {
    return object
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I make an object which is a slice of empty interfaces (following the example in the above):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object := make([]interface{}, 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I assign some values to that slice:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object[0] = []byte("hello")
object[1] = []byte("world")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, we turn the whole thing into an empty interface:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test := makeInterface(object)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, since we have a slice of interfaces, I struggled a bit trying to figure out why this does not work:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for _, item := range test 
    fmt.Println(item)
}

./test.go:46:23: cannot range over test (variable of type interface{})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Type casting
&lt;/h2&gt;

&lt;p&gt;Of course, it makes perfect sense. test is not a slice of empty interfaces, but an empty interface containing a slice of empty interfaces. In order to access those, we first need to cast the interface to a slice of interfaces:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testSlice := test.([]interface{})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can range over this slice and do additional typecasting:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;testSlice := test.([]interface{})
     for _, item := range testSlice {
          byteSlice := item.([]byte)
          fmt.Println(string(byteSlice))
     }

hello
world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>interfaces</category>
      <category>typecasting</category>
    </item>
    <item>
      <title>10 Tips for Tackling Mental Health Issues as a Software Engineer (or Anyone Else, Really)</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 08:57:49 +0000</pubDate>
      <link>https://dev.to/tomdeneire/10-tips-for-tackling-mental-health-issues-as-a-software-engineer-or-anyone-else-really-4f1p</link>
      <guid>https://dev.to/tomdeneire/10-tips-for-tackling-mental-health-issues-as-a-software-engineer-or-anyone-else-really-4f1p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7296%2F0%2Ad9NzobWhcmRotE-_" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7296%2F0%2Ad9NzobWhcmRotE-_" alt="Photo by [Bekir Dönmez](https://unsplash.com/@bekirdonmeez?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@bekirdonmeez?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Bekir Dönmez&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Working as a professional software engineer can be a struggle — not only because of tight deadlines and steep learning curves, but also from a mental health standpoint. Many programmers experience high level of stress, have problems relaxing or sleeping, suffer from impostor syndrome, and ultimately end up battling anxiety, burnout or depression. Having experienced this downward spiral &lt;a href="https://tomdeneire.medium.com/if-err-nil-92b0ab312f7d" rel="noopener noreferrer"&gt;myself&lt;/a&gt;, people often ask me what was the key to my recovery. Obviously, there is no such thing as one easy fix for everyone, but I do have 10 tips that can certainly help to keep you healthy or get you back on the right track. And while I’m writing with software engineers in mind, I’m sure there’s something here for everyone…&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Do What You Love
&lt;/h2&gt;

&lt;p&gt;First of all, I’m a big believer in doing what you love professionally. From the school principle who would rather be a music producer, over the NGO activist who dreams of owning a small book shop, to the data analyst who actually wants to paint fine art — every profession has their share of people who are not happy at their jobs, but stay because of the money, the hours or the prestige. However, in the long run, this only causes frustration and mental exhaustion. So start your journey towards more mental well-being at work by asking yourself: “Do I really enjoy this?” If the answer is no, go do something else. Life’s too short. And if you find yourself thinking “Yes, but…”, read the excellent &lt;a href="https://www.goodreads.com/book/show/25779585-f-k-it-do-what-you-love" rel="noopener noreferrer"&gt;F**ck It. Do What You Love&lt;/a&gt;, by John C. Parkin. He’ll convince you you’ll never be happy if you’re not doing what you love.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Listen To Your Body
&lt;/h2&gt;

&lt;p&gt;Many people who are stuck in an environment they don’t enjoy or under a lot of stress, don’t even realize this themselves. Whether it’s a sense of work ethic, personal pride or financial concern, they just keep going and ignore the alarm bells until it’s too late. At this point, health issues usually kick in. When we experience anxiety and stress, our bodies produce cortisol, adrenaline and noradrenaline. This is a healthy and natural response, but in the case of a chronic build up of such stress hormones, it leads to physical ailments like chronic pain (headaches, back pain), digestive problems (heartburn, constipation), inflammation (skin rashes, bowel problems) or even heart conditions. This is your body’s way of saying “I’ve had enough”, and sooner or later you’ll need to listen to it, because the health issues will only become worse. I’ve experienced it myself and have seen it in many others too. For instance, a former colleague of mine, who struggles with anxiety and fear of failure, went to a dozen doctors over the course of a few years with an ever-growing list of complaints. She tried a number of treatments, spent weeks on medical leave, until she literally couldn’t go on any further. And then she resigned. I hope it was the right decision. Personally, I think the physical stuff was just one side of the story.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Be Honest With Yourself
&lt;/h2&gt;

&lt;p&gt;This dovetails nicely into a third important aspect. Sooner or later (but sooner is better), we all need to starting being honest with ourselves. Often, the truth of the matter is in plain sight. Maybe it’s our partner who has been saying for years that we work too much, maybe it’s that friend who keeps asking “Are you sure you’re alright?”. Tackling mental health problems starts with being completely, even brutally honest with yourself. Look into the mirror, lose the ego, and ask yourself: “Am I happy? Do I love my job? Do I love my life? ” The realization that the answer may be “no”, is often the moment when people “crack”, when they lose the facade and start being honest. It’s hard, mind you, because this is also the moment when things get worse (because now you’re much more aware of them) before they can start getting better. Still, the first important step towards change is admitting you need change.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Go To Therapy
&lt;/h2&gt;

&lt;p&gt;When you need change, you also need help. You often see people’s sense of pride or duty that got them over-stressed in the first place, interfering with their recovery too. Admitting you need to change is one thing, admitting you need help, is quite another. But it’s such an important aspect. We’re all so caught up in our own unique contexts that we often can’t see the forest for the trees. Whether it’s a psychiatrist, a therapist, or just a good friend — they often see truths and solutions, when all you yourself can see are questions and difficulties. Help, and preferably professional help, is extremely valuable for all stages of mental issues, be it a vague sense of bore-out or a full-blown clinical depression.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Face Your Fears
&lt;/h2&gt;

&lt;p&gt;When you start tackling mental issues, things get scary pretty quickly. Admitting you have a problem is scary, seeking out help is scary, talking about your emotions is scary — suddenly you feel very small. But that’s a good thing. If there’s one thing I’ve learned in my own process, it’s how much fear dominates our lives. There are three main types of fear: fear of abandonment fear of change and fear of failure — and together they are the root of many of our negative emotions and thoughts. Especially the last type seems very prominent in software engineering. I’m the first to admit that it was fear of failure that inspired my impostor syndrome, my anxiety, my debilitating perfectionism, my social communication issues, my sleep disorder, my lack of work-life balance. Facing these fears, understanding where they come from, realizing the impact they have on your physical and emotional well-being, and ultimately, learning how you can transform them into strength is the key to getting better.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Anger Management
&lt;/h2&gt;

&lt;p&gt;A good indication of underlying fear, is anger — often also ignored or suppressed for years. This is clearly another area where many people cling to social expectations or the illusion of the moral highroad. People will tell you: “I’m not angry, I’m just &lt;em&gt;(insert other emotion here)&lt;/em&gt;”. They’ll confess to being sad, disappointed, frustrated, and so on, but if you scratch the surface, you’ll soon see how much anger is there. Anger for that colleague who routinely criticizes their code, anger for that manager who has no idea of the complexity of a new feature, anger for themselves because they’ve been working on a problem all day without making any progress… And underneath that anger is fear: fear of the confrontation with said colleague, fear of losing your job, fear of failure. Admitting you’re angry and finding a suitable release for it, is another big step.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Learn To Say No
&lt;/h2&gt;

&lt;p&gt;Recognizing your fears and your anger will soon lead to identifying a number of sore spots in your professional life. You’ll suddenly realize how much certain people, situations or decisions vex you, and once you do, there is no way back. Whereas in the past you’d just ignore colleague A or B as much as possible, you’ll slowly start confronting them. Or, where before you would just go along with the decision to adopt a new framework &lt;em&gt;du jour&lt;/em&gt;, you’ll want to speak up. This is when you learn to say no, which is another thing that is surrounded with social and professional stigma nowadays. You’ll often read about how good employees are people with a &lt;em&gt;Yes mentality&lt;/em&gt;, but for me, being able to say no at the right time is a vastly underrated skill. Saying no is about being assertive, about indicating your personal boundaries and about self-respect.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Eliminate Your Storyteller
&lt;/h2&gt;

&lt;p&gt;People who work in software or other technical environments, are often highly rational. Many will have a strong inner monologue, analyzing weaknesses, questioning decisions, double-checking solutions, imagining worst-case scenarios, and so on. I call this your personal storyteller, and his voice is not always a pleasant one. For some people, myself included, this inner monologue can become relentless and debilitating, second-guessing ourselves every step of the way. Eliminating your storyteller is not an easy task for rational people operating in a rational environment. Getting out of your head involves getting into your body and your gut feelings. This may sound vague and spiritual, but it’s actually highly practical. It’s about stopping your thought process by focusing on the actual experience. For instance, instead of mentally reliving a failed debugging session (“What did I miss? Am I ever going to find the problem?”), you need to focus on that gnawing feeling in your stomach where all of this fear of failure is living. This is not pleasant either, but at least it gives you something concrete to work with. I’ve found that it’s much easier to try and work the fear out of my body, than to stop the creaking cartwheel of my thoughts…&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Lose The Context
&lt;/h2&gt;

&lt;p&gt;Once you’re aware of your storyteller, you’ll notice how much your life is dominated by words and ideas and scenarios. But if you strip all of that “context” away, things get really clear, really quickly. With context, you’ll think of a professional situation like this: “It’s true colleague A belittled me yesterday, but I did make a stupid mistake, didn’t I? Still, he can’t talk to me like that. I mean, okay, I know there’s no ill will involved and he’s had a tough year with COVID and all. So what should I do? If I go to the manager, I’m probably throwing oil on the fire. Maybe I’m overreacting?” And this goes on and on… Without context, the situation is like this: “I feel disrespected by colleague A. This needs to stop. I can’t account for his actions, but I can control mine. So next time I will speak up respectfully, and we’ll see where that gets us.”&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Stop Reading Lists Like This One
&lt;/h2&gt;

&lt;p&gt;At the very end of this list, I have a confession to make. I don’t actually believe in lists like this one, or in a bunch of tips and tricks for complex matters like improving mental health in a professional context. So my final advice is this. If you are experiencing mental issues (personal or professional), seek out help and start working on yourself. Books, podcasts or apps may all help along the way, but real change comes from real work. The kind that is not in a book, but comes for staring hard in the mirror and working on yourself. And while that’s hard work — probably one of the hardest things you’ll ever do — it’s worth it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mentalhealth</category>
      <category>selfimprovement</category>
    </item>
    <item>
      <title>Get started with AWK</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 08:54:56 +0000</pubDate>
      <link>https://dev.to/tomdeneire/get-started-with-awk-56hm</link>
      <guid>https://dev.to/tomdeneire/get-started-with-awk-56hm</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8486%2F0%2ADDKpWAB8buP1BETP" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8486%2F0%2ADDKpWAB8buP1BETP" alt="Photo by [Natalia Yakovleva](https://unsplash.com/@foxfox?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@foxfox?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Natalia Yakovleva&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AWK?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/AWK" rel="noopener noreferrer"&gt;AWK&lt;/a&gt; is a true &lt;strong&gt;GNU/Linux classic&lt;/strong&gt;, designed by Alfred &lt;strong&gt;A&lt;/strong&gt;ho, Peter &lt;strong&gt;W&lt;/strong&gt;einberger, and Brian &lt;strong&gt;K&lt;/strong&gt;ernighan — three of the biggest names in UNIX development and computer science in general. It is a convenient and expressive programming language that can be applied to a wide variety of computing and data-manipulation tasks.&lt;/p&gt;

&lt;p&gt;Of course this tutorial is only a brief overview of the basics of AWK. There are several more elaborated tutorials to be found online, as well as the original manual &lt;a href="https://ia803404.us.archive.org/0/items/pdfy-MgN0H1joIoDVoIC7/The_AWK_Programming_Language.pdf" rel="noopener noreferrer"&gt;The AWK Programming Language&lt;/a&gt; written by the designers…&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow and structure
&lt;/h2&gt;

&lt;p&gt;Starting out, we need to understand the workflow and &lt;strong&gt;program structure&lt;/strong&gt; of AWK.&lt;/p&gt;

&lt;p&gt;An AWK program follows this outline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;execute commands from &lt;code&gt;BEGIN&lt;/code&gt; block&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;read a line from input stream&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;execute commands on a line or rather ‘record’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;repeat if end of file has not been reached&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;execute commands from &lt;code&gt;END&lt;/code&gt; block&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not all steps are necessary. For instance, a valid AWK instruction can be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '/o/ {print}'

one
two
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This only uses the middle or “body” block.&lt;/p&gt;

&lt;p&gt;AWK commands take the form of &lt;strong&gt;pattern-action statements&lt;/strong&gt; with the syntax &lt;code&gt;pattern { action }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If there is a match for the pattern, the action is performed. If there is no pattern, the action is performed for every input line, for instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '{print}'

one
two
three
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Together with the &lt;code&gt;BEGIN&lt;/code&gt; and &lt;code&gt;END&lt;/code&gt; block, this becomes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk 'BEGIN{print "STARTING\n"} {print} END{print "READY"}'

STARTING
one
two
three
READY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By default, AWK separates input into ‘records’ using newlines, but this can be changed (see below).&lt;/p&gt;

&lt;h2&gt;
  
  
  Running an AWK program
&lt;/h2&gt;

&lt;p&gt;There are several ways to run an AWK program.&lt;/p&gt;

&lt;p&gt;We can use AWK as a &lt;strong&gt;command-line application&lt;/strong&gt;, as in the examples above, but we can also provide AWK commands in a &lt;strong&gt;script file&lt;/strong&gt; and use the -f flag:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat input.txt | awk -f script.awk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can use input that is &lt;strong&gt;piped&lt;/strong&gt; to awk, like in the example above, or we can specify a &lt;strong&gt;source file&lt;/strong&gt; (or several) for the text input, e.g.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk '{print}' input.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Built-in variables
&lt;/h2&gt;
&lt;h3&gt;
  
  
  FS, $0, $1, …
&lt;/h3&gt;

&lt;p&gt;As a text processing utility, AWK is designed to split lines into fields. To do this, it uses a built-in variable &lt;code&gt;FS&lt;/code&gt; which defaults to space but which you can change with the &lt;code&gt;-F&lt;/code&gt; flag, like so:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'a b c' | awk '{print $1}'

a

echo 'a,b,c' | awk -F "," '{print $1}'

a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(Similarly, built-in variable &lt;code&gt;RS&lt;/code&gt;, record separator, allows to change the default record separator, which defaults to newline).&lt;/p&gt;

&lt;p&gt;AWK has many such variables, not only the above-mentioned &lt;code&gt;$n&lt;/code&gt; (nth field) or &lt;code&gt;$0&lt;/code&gt; (the entire record), but also, for instance:&lt;/p&gt;

&lt;h3&gt;
  
  
  NF
&lt;/h3&gt;

&lt;p&gt;This represents the number of fields in the current record, which can be used as a pattern to match the input to, for instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'a b c\nd e' | awk 'NF &amp;gt; 2'

a b c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  NR
&lt;/h3&gt;

&lt;p&gt;This represents the index number of the ‘record’ (in this case, line) from the input:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'a b c\nd e' | awk '{print NR}'

1
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  IGNORECASE
&lt;/h3&gt;

&lt;p&gt;Some variables are specific for certain versions of AWK, such as GAWK (GNU AWK), which is the default &lt;code&gt;awk&lt;/code&gt; on many Linux systems. One of those is &lt;code&gt;IGNORECASE&lt;/code&gt; which can be used when matching records to certain patterns (note the &lt;code&gt;/ /&lt;/code&gt; syntax for patterns, see below):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'a b c' | awk '{IGNORECASE = 1} /A/'

a b c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Operators
&lt;/h2&gt;

&lt;p&gt;This overview is too short to discuss AWK operators in full, but let’s look at some examples.&lt;/p&gt;
&lt;h3&gt;
  
  
  Arithmetic
&lt;/h3&gt;

&lt;p&gt;There are only two types of data in awk: strings of characters and numbers. Awk converts strings into numbers using a conversion format (which can be changed using built-in variable &lt;code&gt;CONVFMT&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'a 1 1' | awk '{print ($2 + $3)}'

2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Increment and decrement
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '1 1 1' | awk '{print (++$1)}'

2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Relational
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '1\n0\n7\n0\n3\n0\n4\n2\n3' | awk '$0 != 0'

1
7
3
4
2
3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Assignment
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk 'BEGIN { name = "Tom"; printf "My name is %s", name }'

My name is Tom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By the way, notice how this is an AWK instruction that does not have a body, only a &lt;code&gt;BEGIN&lt;/code&gt; block. Hence it does not need an input to function either… It also uses formatted printing &lt;code&gt;printf&lt;/code&gt; instead of the regular &lt;code&gt;print&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns and regular expressions
&lt;/h2&gt;

&lt;p&gt;AWK’s bread and butter is pattern matching. Moreover, it is very powerful and efficient in handling regular expressions.&lt;/p&gt;

&lt;p&gt;A basic example of this is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '/one/ {print}'

one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;which we can also write using a relational operator for the pattern:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '$0 == "one" {print}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;AWK uses the POSIX regular expression syntax (as do other UNIX utilities, like &lt;code&gt;sed&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2352%2F1%2A_3LAGsB4XavbR1MWEnS_nQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2352%2F1%2A_3LAGsB4XavbR1MWEnS_nQ.png" alt="Source: [https://webannex.blogspot.com/2013/04/regular-expressions-cheat-sheet.html](https://webannex.blogspot.com/2013/04/regular-expressions-cheat-sheet.html)" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Patterns can be combined with parentheses and the logical operators &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt; and &lt;code&gt;!&lt;/code&gt;, which stand for AND, OR, and NOT.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '(/one/) || (/two/) {print}'
one
two
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Patterns are AWK’s true strength, even the keywords &lt;code&gt;BEGIN&lt;/code&gt; and &lt;code&gt;END&lt;/code&gt; mentioned above are, in fact, just patterns…&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Computing with AWK&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Besides text, AWK also handles numerical data well, and is a formidable tool for performing calculations, generating reports, and so on.&lt;/p&gt;

&lt;p&gt;For computations it is often handy to make use of user-created variables, which you do not need to define, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '1\n1\n1' | awk '{total+=$0} END {print total}'

3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Built-in functions
&lt;/h3&gt;

&lt;p&gt;We have already seen that awk provides built-in variables. Similarly, there are built-in functions for computing useful values. There are several kinds of functions such as functions for arithmetic, time, bit manipulation and also text functions. One of these is length, which counts the number of characters in a string:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'one\ntwo\nthree' | awk '{print length($0)}'

3
3
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  User-defined functions
&lt;/h3&gt;

&lt;p&gt;You can also define your own functions with the following syntax:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function function_name(arg1, arg2, ...){function body}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Returning value with return is optional.&lt;/p&gt;

&lt;p&gt;A basic example is a function that returns the minimum number:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e '1 2\n4 3\n5 7' | awk 'function min(num1,num2){if (num1 &amp;lt; num2) return num1 else return num2}{print min($1,$2)}'
1
3
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Of course, such an example would be more legible in an AWK script than a oneliner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Control-flow
&lt;/h2&gt;

&lt;p&gt;The previous example already showed that AWK is also capable of if-else statements for making decisions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (condition)
action-1
else
action-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It also has the ability to create for loops:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (initialization; condition; increment/decrement)
action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(Both are modeled on the syntax of the C programming language)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk 'BEGIN { for (i = 1; i &amp;lt;= 5; ++i) print i }'

1
2
3
4
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Arrays
&lt;/h2&gt;

&lt;p&gt;Awk provides arrays for storing groups of related values. These are very powerful as they can even be multidimensional.&lt;/p&gt;

&lt;p&gt;A simple example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e 'Tom 1\nHarry 2\nTom 3\nHarry 4\nJimmy 5' | awk '{total[$1]+=$2} END {print total["Tom"]}'

5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  AWK as a scripting language
&lt;/h2&gt;

&lt;p&gt;A more elaborate example shows how AWK can be a valid alternative for Python or other scripting languages. (Also keep in mind that in some programming environments (servers, for instance) you might not have access to Python or your favourite scripting language, or limited possibilities to upload source code files!)&lt;/p&gt;

&lt;p&gt;Let’s count all &lt;code&gt;.json&lt;/code&gt;, &lt;code&gt;.xml&lt;/code&gt; and &lt;code&gt;.csv&lt;/code&gt; files in my Dropbox folder.&lt;/p&gt;

&lt;p&gt;Let’s first gather all files recursively into a source file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find /home/tdeneire/Dropbox/. -not -type d &amp;gt; files.txt
wc -l files.txt 

132899 files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This amounts to some 130K files.&lt;/p&gt;

&lt;p&gt;In Python we could do something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;total = {}

with open("/home/tdeneire/Dropbox/files.txt", "r") as reader:
    for line in reader:
        line = line.strip()
        extension = line.split(".")[-1]
        total.setdefault(extension, 0)
        total[extension] += 1

for key in ["json", "xml", "csv"]:
    print(key, total[key])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In AWK:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk -F "." '{extension=$(NF); total[extension]+=1} END {wanted["json"]; wanted["csv"]; wanted["xml"]; for (ext in wanted){print ext,total[ext]}}' /home/tdeneire/Dropbox/files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this particular example, AWK is much slower than Python (about 2.5 times slower), but if we play to AWK’s strengths, i.e. pattern matching, for instance, searching for ten consecutive digits, matters are quickly reversed.&lt;/p&gt;

&lt;p&gt;In Python&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import re

with open("/home/tdeneire/Dropbox/files.txt", "r") as reader:
    for line in reader:
        line = line.strip()
        if re.match('.*[0-9]{10}', line):
            print(line)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With AWK:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;awk -F "." '/.*[0-9]{10}/' /home/tdeneire/Dropbox/files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Difference:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time py3 test.py

real 0m1.296s
user 0m0.693s
sys  0m0.143s

time awk -F "." '/.*[0-9]{10}/' /home/tdeneire/Dropbox/files.txt

real 0m0.659s
user 0m0.105s
sys  0m0.113s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This just goes to show the importance of picking the &lt;strong&gt;right tool for the job&lt;/strong&gt; for scripting.&lt;/p&gt;

&lt;p&gt;But in some cases that tool might just be AWK, even if it’s over 40 years old!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.tutorialspoint.com/awk" rel="noopener noreferrer"&gt;https://www.tutorialspoint.com/awk&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aho, Alfred V.; Kernighan, Brian W.; Weinberger, Peter J., &lt;a href="https://ia803404.us.archive.org/0/items/pdfy-MgN0H1joIoDVoIC7/The_AWK_Programming_Language.pdf" rel="noopener noreferrer"&gt;*The AWK programming language&lt;/a&gt;* (Reading, Mass.: 1988), ISBN-10 0-201-07981-X&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>awk</category>
      <category>linux</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Catching Go errors with errors.Is()</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 08:46:03 +0000</pubDate>
      <link>https://dev.to/tomdeneire/catching-go-errors-with-errorsis-14bk</link>
      <guid>https://dev.to/tomdeneire/catching-go-errors-with-errorsis-14bk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F12000%2F0%2ACOSHG9hBnKhiiwUn" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F12000%2F0%2ACOSHG9hBnKhiiwUn" alt="Photo by [David Pupaza](https://unsplash.com/@dav420?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="600" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@dav420?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;David Pupaza&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Go error handling
&lt;/h2&gt;

&lt;p&gt;Anyone who has done some development in Go will be familiar with the Go philosophy on error handling and the following pattern:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;result, err := myFunc(args)
 if err != nil {
  // do something
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Catching errors
&lt;/h2&gt;

&lt;p&gt;As many Gophers, over time I have grown accustomed to the inevitability of Go’s errors and come to appreciate this explicit and sturdy way of handling errors. Up till recently, however, there was one aspect about Go errors that kept confusing me, namely how to catch *specific *errors.&lt;/p&gt;

&lt;p&gt;Let’s look at the following example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file, err := os.Open("myfile")
   if err != nil {
       // handle error
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In a case like this, coming from a Python background, I would like to use &lt;em&gt;try…catch…&lt;/em&gt; pattern, for instance, to create myfile should it not exist.&lt;/p&gt;

&lt;p&gt;In idiomatic Go there are two solutions for this.&lt;/p&gt;

&lt;p&gt;The first is to rewrite the code to first check whether the file exists (you can use os.Stat() for that) and, if not, create it — this is probably preferable in this case.&lt;/p&gt;

&lt;p&gt;The second is to make use of errors.Is() — this can be used if there is no workaround (see below).&lt;/p&gt;
&lt;h2&gt;
  
  
  errors.Is()
&lt;/h2&gt;

&lt;p&gt;Go’s error package has a function &lt;a href="https://pkg.go.dev/errors#Is" rel="noopener noreferrer"&gt;errors.Is()&lt;/a&gt;that enables you to test a certain error against a &lt;em&gt;target&lt;/em&gt;, like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this way, we are able to catch a specific case of the possible errors returned by os.Open() , namely “file does not exist”, as different from, for instance, “permission denied”.

&lt;p&gt;However, it can be a bit tricky to find the correct target to test an error against. Whereas other languages like Python will print a specific code in the error output (in this case &lt;a href="https://docs.python.org/3/library/exceptions.html#FileNotFoundError" rel="noopener noreferrer"&gt;FileNotFoundError&lt;/a&gt;) which you can then use as an exception, Go will only print the string representation of the error:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;open myfile: no such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In Go you can either test against errors you define yourself, or generic system errors, like the ones defined in package &lt;a href="https://pkg.go.dev/io/fs#pkg-variables" rel="noopener noreferrer"&gt;io/fs&lt;/a&gt; :&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var (
    ErrInvalid    = errInvalid()    // "invalid argument"
    ErrPermission = errPermission() // "permission denied"
    ErrExist      = errExist()      // "file already exists"
    ErrNotExist   = errNotExist()   // "file does not exist"
    ErrClosed     = errClosed()     // "file already closed"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Another case where these predefined error variables are useful, is the &lt;a href="https://pkg.go.dev/database/sql#pkg-variables" rel="noopener noreferrer"&gt;sql&lt;/a&gt; package, as even “no rows found” is an error in Go:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var ErrNoRows = errors.New("sql: no rows in result set")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This is a clear example of where you cannot work around the error and would want to specifically test it, since you would like to catch “no rows”, but still have the software fail at something like a connection error! Just have a look at an an example from the documentation:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  errors.As()
&lt;/h2&gt;

&lt;p&gt;Finally, there is also another function, &lt;a href="https://pkg.go.dev/errors#As" rel="noopener noreferrer"&gt;errors.As()&lt;/a&gt; ,which lets you use the error target:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Output:

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed at path: non-existing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For more information on this advanced variation of the pattern, have a look at the &lt;a href="https://pkg.go.dev/errors#As" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>errors</category>
    </item>
    <item>
      <title>What every programmer should know about Alan Turing</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 08:41:37 +0000</pubDate>
      <link>https://dev.to/tomdeneire/what-every-programmer-should-know-about-alan-turing-27g2</link>
      <guid>https://dev.to/tomdeneire/what-every-programmer-should-know-about-alan-turing-27g2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F12000%2F0%2A4ARxt2L69d2fD7mn" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F12000%2F0%2A4ARxt2L69d2fD7mn" alt="Enigma encryption-machine — Photo by [Mauro Sbicego](https://unsplash.com/@maurosbicego?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="760" height="506"&gt;&lt;/a&gt;&lt;br&gt;
Enigma encryption-machine — Photo by &lt;a href="https://unsplash.com/@maurosbicego?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Mauro Sbicego&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Biography
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Alan_Turing" rel="noopener noreferrer"&gt;Alan Turing&lt;/a&gt; (1912–1954) was a British mathematician, who was highly influential in the development of theoretical computer science. Turing formalized the concepts of algorithm and computation by describing the so-called &lt;em&gt;Turing machine&lt;/em&gt;, which can be considered a model of a general-purpose computer. Turing is widely considered to be the father of computer science and artificial intelligence.&lt;/p&gt;

&lt;p&gt;Outside the realm of computer science, Turing is especially remembered for the role he played in World War Two whilst working for Britain’s codebreaking centre. He was particularly instrumental in improving the Allied techniques for breaking the ciphers of the famous &lt;a href="https://en.wikipedia.org/wiki/Enigma_machine" rel="noopener noreferrer"&gt;Enigma machine&lt;/a&gt;, which was used extensively by Nazi Germany to encipher even their most top-secret military messages.&lt;/p&gt;

&lt;p&gt;Sadly, despite his accomplishments in both cryptanalysis and computer science, Turing — who often worked under the cover of secrecy — was never fully recognized in his home country. To boot, in 1952, Turing was prosecuted for &lt;a href="https://en.wikipedia.org/wiki/Gross_indecency" rel="noopener noreferrer"&gt;homosexual acts&lt;/a&gt;. He accepted &lt;a href="https://en.wikipedia.org/wiki/Chemical_castration" rel="noopener noreferrer"&gt;chemical castration&lt;/a&gt;, which rendered him impotent and caused him to grow breasts, as an alternative to prison. Turing died in 1954, at home, at only 41 years old, from eating an apple poisoned with cyanide. Although the circumstances of his death remain unclear, it appears most likely that he took his own life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turing machines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Computing
&lt;/h3&gt;

&lt;p&gt;Turing first described his “computing” machine in 1936 with a strictly mathematical purpose. Without going into too much detail, Turing was basically looking for a way to prove that while it is possible to formulate a procedure to produce all &lt;a href="https://en.wikipedia.org/wiki/Rational_number" rel="noopener noreferrer"&gt;rational numbers &lt;/a&gt;— numbers that can be expressed as a fraction, e.g. 1 (1/1), 0.5 (1/2) or 0.333… (1/3) — , it is impossible to formulate such a procedure for &lt;em&gt;all&lt;/em&gt; &lt;a href="https://en.wikipedia.org/wiki/Real_number" rel="noopener noreferrer"&gt;real numbers&lt;/a&gt;, which include the &lt;a href="https://en.wikipedia.org/wiki/Irrational_number" rel="noopener noreferrer"&gt;irrational numbers&lt;/a&gt;, which cannot be expressed as a fraction, e.g. &lt;a href="https://en.wikipedia.org/wiki/Square_root_of_2" rel="noopener noreferrer"&gt;√2&lt;/a&gt; or π.&lt;/p&gt;

&lt;p&gt;The problem with the irrationals is that while they contain some numbers that are &lt;a href="https://en.wikipedia.org/wiki/Computable_number" rel="noopener noreferrer"&gt;computable&lt;/a&gt; — i.e. numbers that can be computed to within any desired precision by a finite, terminating process, like the examples of √2 or π, the vast majority of the irrational numbers cannot be computed. They consist of a purely random, infinite progression of digits without a discernible pattern, such as 0.2896574609817847850521… There is no way to formally describe how to produce such numbers.&lt;/p&gt;

&lt;p&gt;The notion “computability” is a good way to understand what a Turing machine is supposed to do. It is a machine that, given a set of instructions, is able to compute numbers, even if their decimal expansion goes on for ever. It is not the end result that counts, but the formal procedure required to produce that result. For instance, we can easily think of a set of instructions to produce 1/3:&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;It could be something like (this is not how Turing does it, but that does not matter for now):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**A**: print "0"
**B**: print "."
**C**: print "3"
**D**: goto **C**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I’m using instructions here that will ring a bell for anyone familiar with computer science and although this is not exactly how Turing designed his machine, it is the logical consequence of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turing machine
&lt;/h3&gt;

&lt;p&gt;In actuality, a Turing machine is more like a typewriter, which can both print and read characters or “symbols”, with a head that can move both left and right, and working on an infinite one-dimensional tape divided into cells. The machine’s actions are not so much the result of “instructions” (that would imply that it can be programmed), but of “states” or “configurations”. In a certain state a machine will perform a certain action (Turing also allows series of actions) depending on which symbol it reads at the current position of the head. These actions can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;print a symbol&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;erase a symbol&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;move to the right&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;move to the left&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change to another state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although difficult to believe at first, this unbelievably simple, even “slavish” (in Turing’s own words) machine, that in itself is not even able to do simple addition or multiplication, can be used to print every computable number. For instance, we can easily see that how the machine’s possibility for conditional logic means that we can construct a Turing machine that keeps repeating the sequence 0123456789:&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;In his original 1936 paper, Turing gives even more difficult examples, such as this one (with increasingly larger sequences of 0):&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Any finite “algorithm” — a word I have carefully avoided so far, because it is of course anachronistic — one can think of to construct a number, can be formulated as a specific Turing machine. What’s more, it is possible to design a &lt;a href="https://en.wikipedia.org/wiki/Universal_Turing_machine" rel="noopener noreferrer"&gt;Universal Turing machine&lt;/a&gt;: one &lt;em&gt;single&lt;/em&gt; machine (&lt;strong&gt;U&lt;/strong&gt;) that can be fed as input the description of &lt;em&gt;any other&lt;/em&gt; specific machine (&lt;strong&gt;M&lt;/strong&gt;), and will consequently compute the same number as &lt;strong&gt;M&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you consider what Turing is describing here — the notion of I/O, machine states or instructions implementing an algorithm’s logic, a stream of binary data (Turing used binary fractions exclusively), a way to “store” programs, and so on — it is easy to see how the Turing machine is widely considered a basic model for a general computer as we know it today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turing completeness
&lt;/h3&gt;

&lt;p&gt;A system of data-manipulation rules, such as a computer’s instruction set or a programming language, is said to be &lt;a href="https://en.wikipedia.org/wiki/Turing_completeness" rel="noopener noreferrer"&gt;Turing-complete&lt;/a&gt;, if it can be used to simulate any Turing machine. For example, an imperative language is Turing-complete if it has conditional branching and the ability to change an arbitrary amount of memory.&lt;/p&gt;

&lt;p&gt;Of course, all well-known programming languages are Turing complete, and so are some lesser-known, esoteric ones like &lt;a href="https://en.wikipedia.org/wiki/Whitespace_(programming_language)" rel="noopener noreferrer"&gt;Whitespace&lt;/a&gt;, in which only spaces, linefeeds and tabs have meaning, or Piet, whose programs are bitmaps that look like abstract art. However, it might come as a surprise that even programs like &lt;a href="https://visualstudiomagazine.com/articles/2021/01/27/excel-lambda.aspx" rel="noopener noreferrer"&gt;Microsoft Excel&lt;/a&gt; or &lt;a href="http://sigbovik.org/2017/proceedings.pdf" rel="noopener noreferrer"&gt;Powerpoint&lt;/a&gt; are Turing-complete. This means that, at least in theory, they are completely equivalent to any other Turing-complete language. Imagine writing an operating system in Powerpoint slides! And we can go further still: even video games like &lt;em&gt;Minecraft&lt;/em&gt;, card games like &lt;em&gt;Magic: The Gathering&lt;/em&gt;, and chemical reaction networks have been shown to be Turing-complete!&lt;/p&gt;

&lt;p&gt;Notable examples of incomplete languages are markup languages such as HTML or XML, or query languages. Standard SQL, for instance, is not Turing-complete, although with &lt;a href="https://stackoverflow.com/questions/900055/is-sql-or-even-tsql-turing-complete" rel="noopener noreferrer"&gt;some additions&lt;/a&gt; it can be made so. Regular expression languages and parsing languages are also not Turing-complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turing test
&lt;/h2&gt;

&lt;p&gt;In his writings, Turing often connected his computing machine to the way the human mind works. For instance, he likened the states of the machine to the state of mind of a person performing computations. Vice versa, it is possible that he modeled certain aspects of the Turing machine on the way humans calculate. This interest lead Turing to explore what we would now call “artificial intelligence”.&lt;/p&gt;

&lt;p&gt;Beside the apparent resemblance of the human mind and his computing machine, it is not difficult to see how Turing would arrive at the notion of making machines “intelligent”. Let’s go back to the Universal Turing machine, which builds on the fact that it is possible to describe or encode any Turing machine as a string. Conversely, any string that can be produced by an algorithm can be formulated by a Turing machine. Hence, it is conceivable that we create an algorithm that produces the encoding of a Turing machine! In other words, &lt;em&gt;software writing software&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When thinking about the problem of artificial intelligence, Turing proposed what he called the “imitation game” (hence the 2014 &lt;a href="https://en.wikipedia.org/wiki/The_Imitation_Game" rel="noopener noreferrer"&gt;movie&lt;/a&gt; about Turing’s life), nowadays known as the &lt;a href="https://en.wikipedia.org/wiki/Turing_test" rel="noopener noreferrer"&gt;Turing test&lt;/a&gt;. The test is designed to determine whether a machine is able to exhibit intelligent behaviour indistinguishable from that of a human. In the standard interpretation, it is a conversation between a human interrogator and two other parties, one of which is a machine. The “game” is to determine which one is human and which is not, using written communication only (to rule out factors like articulation, tone, etcetera).&lt;/p&gt;

&lt;p&gt;While machines have been able to pass the Turing test since the &lt;a href="https://en.wikipedia.org/wiki/ELIZA" rel="noopener noreferrer"&gt;60s&lt;/a&gt;, it remains a highly influential, but also widely criticized way to approach artificial intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to know more?
&lt;/h2&gt;

&lt;p&gt;A lot more can be said about Turing machines or Alan Turing’s influence on theoretical computer science in general, and this short blog cannot really do justice to the richness of his ideas.&lt;/p&gt;

&lt;p&gt;For those who want to know more, I highly recommend reading &lt;a href="https://en.wikipedia.org/wiki/The_Annotated_Turing" rel="noopener noreferrer"&gt;*The Annotated Turing: A Guided Tour Through Alan Turing’s Historic Paper on Computability and the Turing Machine&lt;/a&gt; &lt;em&gt;(2008)&lt;/em&gt; *by Charles Petzold (ISBN &lt;a href="https://en.wikipedia.org/wiki/Special:BookSources/978-0-470-22905-7" rel="noopener noreferrer"&gt;978–0–470–22905–7&lt;/a&gt;). It is written as a commentary to Turing’s original paper “On Computable Numbers, with an Application to the &lt;a href="https://en.wikipedia.org/wiki/Entscheidungsproblem" rel="noopener noreferrer"&gt;Entscheidungsproblem&lt;/a&gt;” (doi:&lt;a href="https://doi.org/10.1112%2Fplms%2Fs2-42.1.230" rel="noopener noreferrer"&gt;10.1112/plms/s2–42.1.230&lt;/a&gt;). However, it not only takes the reader sentence by sentence through Turing’s paper, but adds explanations, further examples, corrections, and biographical information. Also, it requires nothing but a general, high-school level of mathematics to start with.&lt;/p&gt;

&lt;p&gt;In short, this is an invaluable source for those who want to explore Alan Turing’s groundbreaking insights on the power of mechanical computation, and — more importantly — its fundamental limitations.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>turing</category>
      <category>programming</category>
      <category>mathematics</category>
    </item>
    <item>
      <title>Shell in a nutshell</title>
      <dc:creator>Tom Deneire ⚡</dc:creator>
      <pubDate>Sat, 11 Feb 2023 08:35:14 +0000</pubDate>
      <link>https://dev.to/tomdeneire/shell-in-a-nutshell-342k</link>
      <guid>https://dev.to/tomdeneire/shell-in-a-nutshell-342k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8000%2F0%2AYxd_yyysX4QWrZaY" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F8000%2F0%2AYxd_yyysX4QWrZaY" alt="Photo by [Jonas Dücker](https://unsplash.com/@jonasduecker?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@jonasduecker?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Jonas Dücker&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://medium.com/analytics-vidhya/dev-101-terminal-velocity-8cbf6f132748" rel="noopener noreferrer"&gt;another blog&lt;/a&gt;, I explained the concept of the &lt;em&gt;shell&lt;/em&gt; — a command language interpreter that executes commands read from standard input, a command line string, or a specified file.&lt;/p&gt;

&lt;p&gt;This means that shell can be used either interactively via the terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tdeneire@XPS-13-9370:~$ sh
$ echo "hello"
hello
$ exit
tdeneire@XPS-13-9370:~$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or as a CLI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sh -c "echo $(date)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or to execute Shell scripts, saved as .shfiles like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh

echo "Hello world"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can then execute them with &lt;code&gt;sh myfile.sh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Especially the last option is a fantastic tool for writing scripts for automation, installation, configuration, and so on.&lt;/p&gt;

&lt;p&gt;Because knowing your way around Shell scripts is a vital tool for any developer working with UNIX systems, I will try to summarize Shell syntax below.&lt;/p&gt;

&lt;p&gt;I’ve taken care to limit this summary to “pure” UNIX shell syntax, i.e. the Bourne shell or sh . Most Unix-like systems contain the file /bin/sh that is either the Bourne shell, or a symbolic link (or hard link) to a compatible shell (e.g. dash). The reason for sticking to sh is that different shell versions (bash, dash, ksh, zsh, …) all come with different features, although they are mostly sh-compatible. By sticking to sh syntax you allow your scripts to be executed by a variety of shells, which makes them dependable and robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello world
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello World!"&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Comments&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This is a comment&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Variable assignment&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME_1="Tom"    # set&lt;br&gt;
readonly NAME_1 # read-only&lt;br&gt;
unset NAME_1    # unset&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Quoting (strong vs weak)&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Quoting variables prevents word splitting and glob expansion, and prevents the script from breaking when input contains spaces, line feeds, glob characters and such.&lt;/em&gt;&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ echo '$HOME'&lt;br&gt;
$HOME&lt;br&gt;
$ echo "$HOME"&lt;br&gt;
/home/tdeneire&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Arrays&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# POSIX shell does not support array variables!&lt;br&gt;
# dash, bash, ksh and others do, however&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  User input&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Enter user name: "&lt;br&gt;
read -r FIRST_NAME&lt;br&gt;
echo "Current user name is $FIRST_NAME"&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Operators (arithmetic)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VAL=$((2 + 2))

&lt;p&gt;# +  (Addition) &lt;br&gt;
# -  (Subtraction) &lt;br&gt;
# *  (Multiplication)&lt;br&gt;
# /  (Division) &lt;br&gt;
# %  (Modulus) &lt;br&gt;
# =  (Assignment) &lt;br&gt;
# == (Equality) &lt;br&gt;
# != (Not Equality)&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Operators (relational)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ "$VAL" -eq 4 ]&lt;br&gt;
# -eq (equal)&lt;br&gt;
# -ne (not equal)&lt;br&gt;
# -gt (greater than)&lt;br&gt;
# -lt (less than)&lt;br&gt;
# -ge (greater or equal)&lt;br&gt;
# -le (less or equal)&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Operators (boolean)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# &amp;amp;&amp;amp; (AND)&lt;br&gt;
# || (OR)&lt;br&gt;
# !  (NOT)&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Operators (string)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME="Tom"&lt;br&gt;
[ "$NAME" = "Tom" ]

&lt;p&gt;# =   (equal)&lt;br&gt;&lt;br&gt;
# !=  (not equal)&lt;br&gt;
# -z  (zero length)&lt;br&gt;&lt;br&gt;
# -n  (non-zero length)&lt;br&gt;
# str (not empty)&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conditional statements (if…elif…else)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME="Tom"

&lt;p&gt;if [ "$NAME" = "Tom" ];&lt;br&gt;
then&lt;br&gt;
    echo "me"&lt;br&gt;
elif [ "$NAME" = "Peter" ];&lt;br&gt;
then&lt;br&gt;
    echo "my cousin"&lt;br&gt;
else&lt;br&gt;
    echo "someone else"&lt;br&gt;
fi&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conditional statements (case)&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME="Tom"

&lt;p&gt;case $NAME in&lt;br&gt;
    "Tom")&lt;br&gt;
        echo "me"&lt;br&gt;
    ;;&lt;br&gt;
    "Peter")&lt;br&gt;
        echo "my cousin"&lt;br&gt;
    ;;&lt;br&gt;
    *)&lt;br&gt;
        echo "someone else"&lt;br&gt;
    ;;&lt;br&gt;
esac&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Loops&lt;br&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for NUMBER in 0 1 2 3 4 5 6 7 8 9&lt;br&gt;
do&lt;br&gt;
    echo $NUMBER&lt;br&gt;
done&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  While&lt;br&gt;
&lt;/h3&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I=0&lt;br&gt;
while [ $I -lt 10 ]&lt;br&gt;
do&lt;br&gt;
    echo $I&lt;br&gt;
    I=$(($I + 1))&lt;br&gt;
done&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Until&lt;br&gt;
&lt;/h3&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I=0&lt;br&gt;
until [ ! $I -lt 10 ]&lt;br&gt;
do&lt;br&gt;
    echo $I&lt;br&gt;
    I=$(($I + 1))&lt;br&gt;
done&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Break&lt;br&gt;
&lt;/h3&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for VAR1 in 1 2 3&lt;br&gt;
do&lt;br&gt;
    for VAR2 in 0 5&lt;br&gt;
    do&lt;br&gt;
        if [ $VAR1 -eq 2 ] &amp;amp;&amp;amp; [ $VAR2 -eq 0 ]&lt;br&gt;
        then&lt;br&gt;
            break 2&lt;br&gt;
        else&lt;br&gt;
            echo "$VAR1 $VAR2"&lt;br&gt;
        fi&lt;br&gt;
    done&lt;br&gt;
done&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Continue&lt;br&gt;
&lt;/h3&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NUMS="1 2 3 4 5 6 7"

&lt;p&gt;for NUM in $NUMS&lt;br&gt;
do&lt;br&gt;
    Q=$(($NUM % 2))&lt;br&gt;
    if [ $Q -eq 0 ]&lt;br&gt;
    then&lt;br&gt;
        echo "$NUM is an even number"&lt;br&gt;
        continue&lt;br&gt;
    fi&lt;br&gt;
    echo "Found odd number: $NUM"&lt;br&gt;
done&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Command substitution&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Date is $(date)"&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Functions&lt;br&gt;
&lt;/h2&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello () {&lt;br&gt;
    echo "Hello, $1"&lt;br&gt;
    return 0  # Can only return 0-255. Other data should be written&lt;br&gt;&lt;br&gt;
    to stdout&lt;br&gt;
}

&lt;p&gt;Hello "Tom"&lt;br&gt;
RETURN=$?&lt;/p&gt;

&lt;p&gt;echo "This command exited with code $RETURN"&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Sources&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.grymoire.com/Unix/Sh.html" rel="noopener noreferrer"&gt;&lt;strong&gt;POSIX Shell Tutorial&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://steinbaugh.com/posts/posix.html" rel="noopener noreferrer"&gt;&lt;strong&gt;POSIX shell cheat sheet&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/dylanaraps/pure-sh-bible" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external…&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tutorialspoint.com/unix/shell_scripting.htm" rel="noopener noreferrer"&gt;&lt;strong&gt;Shell Scripting Tutorial&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out &lt;a href="https://tomdeneire.github.io/" rel="noopener noreferrer"&gt;https://tomdeneire.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>shell</category>
      <category>bash</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
