<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Łukasz Tenerowicz</title>
    <description>The latest articles on Forem by Łukasz Tenerowicz (@konkit).</description>
    <link>https://forem.com/konkit</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%2F18573%2Fe783e56d-1132-4082-8526-ea421c74b477.jpg</url>
      <title>Forem: Łukasz Tenerowicz</title>
      <link>https://forem.com/konkit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/konkit"/>
    <language>en</language>
    <item>
      <title>Inbox Zero with Gmail</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Sun, 24 Jan 2021 18:29:33 +0000</pubDate>
      <link>https://forem.com/konkit/inbox-zero-with-gmail-19f1</link>
      <guid>https://forem.com/konkit/inbox-zero-with-gmail-19f1</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46AGmHff--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4o8ihlyfvx1ernjc40da.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46AGmHff--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4o8ihlyfvx1ernjc40da.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Too many times I’ve heard someone saying “Don’t send me any emails, I won’t read them anyway, my mailbox is a mess”.&lt;/p&gt;

&lt;p&gt;That’s just sad. But it doesn’t have to be like this.&lt;/p&gt;

&lt;p&gt;Right now, in my Gmail mailbox, there are zero messages. It’s empty. It’s not an anomaly, it’s usually like that because of a method called &lt;strong&gt;Inbox Zero.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, so what’s this Inbox Zero?
&lt;/h2&gt;

&lt;p&gt;The whole process is easy – we should think about our email inbox as a &lt;strong&gt;task list&lt;/strong&gt; , where we do a single task, put a tick sign on it to mark it as done, and move to the next one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zMAC1Oyu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Untitled-2021-01-09-1513-1024x483.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zMAC1Oyu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Untitled-2021-01-09-1513-1024x483.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another metaphor could be a &lt;strong&gt;computer program&lt;/strong&gt; in the form of a list of CPU instructions. The most basic activity of a typical CPU is to load an instruction, do an action according to that instruction and move to the next one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6zBGdRJf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/inbox-to-asm-1024x480.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6zBGdRJf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/inbox-to-asm-1024x480.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back to our mailboxes. Our inbox should be a single list of messages. No priorities, no stars, no categories, etc. Just a list of messages, that we haven’t processed yet.&lt;/p&gt;

&lt;p&gt;When we check our mailbox, we should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read the first email on top&lt;/li&gt;
&lt;li&gt;do an appropriate action&lt;/li&gt;
&lt;li&gt;mark the message as done, thus removing it from our inbox&lt;/li&gt;
&lt;li&gt;move to the next email. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We repeat the process until there are no messages left in our inbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aHbI84B3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Reply_forward-1024x267.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aHbI84B3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Reply_forward-1024x267.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Marking emails as “done”.
&lt;/h2&gt;

&lt;p&gt;It’s obvious, that if we want to clean up our mailbox, we should somehow reduce the count of our messages.&lt;/p&gt;

&lt;p&gt;Back when &lt;a href="https://en.wikipedia.org/wiki/Inbox_by_Gmail"&gt;Inbox by Gmail&lt;/a&gt; was a thing (&lt;a href="https://killedbygoogle.com/"&gt;may it rest in peace&lt;/a&gt;), we could get rid of a processed email by clicking a tick button – the email would disappear, and we could check the next one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mo1C2HTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/google-inbox-done-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mo1C2HTz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/google-inbox-done-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the hood, those emails were simply &lt;strong&gt;archived&lt;/strong&gt;. Therefore, even though there is no tick button in Gmail, we can still use the Archive button and achieve the same results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1BI5DMuJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmai-archive.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1BI5DMuJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmai-archive.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not only will it make a message disappear from our Inbox, which is exactly what we want, but on the other hand, if we ever need that message (or if we simply fear losing it), it’s not deleted, it’s always there under the “All mail” section.&lt;/p&gt;

&lt;p&gt;On the mobile Gmail app it’s even easier, you just need to swipe right:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mlwhrfI7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-archive-mobile-1-1024x768.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mlwhrfI7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-archive-mobile-1-1024x768.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Snooze
&lt;/h2&gt;

&lt;p&gt;Another great feature of Inbox ported to Gmail itself is a &lt;strong&gt;snooze&lt;/strong&gt; functionality. If the email is about doing some action, but we can’t do it right away, we don’t have to hold this email in our inbox. We can schedule the message to reappear in our inbox at a selected time. When we do it, the message disappears, and we can move to the next email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EMtWpx6X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-snooze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EMtWpx6X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-snooze.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The mobile app has this feature too, just swipe left:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B1jcnOrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-mobile-snooze-1024x778.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B1jcnOrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/gmail-mobile-snooze-1024x778.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reply
&lt;/h2&gt;

&lt;p&gt;Well, emails are about communication after all and even though we mostly read stuff (like notifications, newsletters, etc.), sometimes we receive an actual message we have to reply to.&lt;/p&gt;

&lt;p&gt;The funny concept I discovered that may be helpful here is “&lt;a href="https://www.buzzfeednews.com/article/katienotopoulos/i-tried-emailing-like-your-boss"&gt;replying like a CEO&lt;/a&gt;“. Basically, it’s an approach where you reply even with just a few words, but right away. I remember that one of our professors at the university had this style of communication. When someone wrote him a long, elegant, respectful email, he simply replied with “OK”. Back then it was ridiculous to me. Now I get it, and given the number of students that he had to reply to, I would probably do the same.&lt;/p&gt;

&lt;p&gt;The bottom line is, do whatever helps you to minimize the time you spend processing the message, so you can move to the next one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filters
&lt;/h2&gt;

&lt;p&gt;The Inbox Zero technique might seem counterproductive if we receive a lot of emails. This is where filters are a great help.&lt;/p&gt;

&lt;p&gt;When we receive far too many messages of a given kind or if they aren’t that important, we can filter them out, by specifying criteria about sender address or message’s content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e_4bbkjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.04-1-1024x539.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_4bbkjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.04-1-1024x539.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DSCPJL09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.15-2-1024x539.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DSCPJL09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.15-2-1024x539.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this view, we can specify what should happen with this message. We can simply make it skip the inbox, we can also assign it a label if it is one of those emails we sometimes read, but we don’t want it to distract us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P-LmHx55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.33-1-1024x545.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P-LmHx55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.05.33-1-1024x545.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here we go – the inbox is clear, but at the same time those filtered messages are easy to find.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RVPt9Vaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.06.23-2-1024x545.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RVPt9Vaa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.06.23-2-1024x545.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RafmM7V_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.06.43-1-1024x545.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RafmM7V_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2021/01/Zrzut-ekranu-2020-09-13-o-18.06.43-1-1024x545.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  But how do I start? I already have a mess in my mailbox …
&lt;/h2&gt;

&lt;p&gt;The solution is simple – select all emails older than a week (or a month) and archive them. If they are this old, you probably won’t need them anymore. However, if you do, they are always there under “All mail”.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the profits?
&lt;/h2&gt;

&lt;p&gt;Messages you’ve dealt with already won’t distract you. Not only because they disappear from your inbox, but also because of the “Zeigarnik’s effect”. It was discovered, that we tend to remember unfinished things better. If we mark a message as done, it’s easier for our mind to think of it as a finished thing, and we can focus on other activities.&lt;/p&gt;

&lt;p&gt;The other profit is that you won’t miss any emails – because you read and process each of them.&lt;/p&gt;

&lt;p&gt;Additionally, if we “unclog” our mailboxes, we could use it as a “low priority communication channel”. We can agree within our team, that we send the important stuff via Slack or other IM platform we use and if we don’t need the answer within the next few hours, we send it via email. The result is that you and your teammates are less distracted. However, the important prerequisite is that you have to agree on that way of communicating within your team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you think?
&lt;/h2&gt;

&lt;p&gt;Have you tried this technique? Maybe in some different flavor? What do you think about it? If you’ve reached that far, you surely can let me know in the comments! 😉&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konkit.tech/2021/01/24/inbox-zero-with-gmail/"&gt;Inbox Zero with Gmail&lt;/a&gt; appeared first on &lt;a href="https://konkit.tech"&gt;Konkit's Tech Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>email</category>
      <category>tips</category>
      <category>inboxzero</category>
    </item>
    <item>
      <title>My journey through JVM languages</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Sun, 25 Oct 2020 18:06:48 +0000</pubDate>
      <link>https://forem.com/konkit/my-journey-through-jvm-languages-52bp</link>
      <guid>https://forem.com/konkit/my-journey-through-jvm-languages-52bp</guid>
      <description>&lt;p&gt;Java is not just a language. The real reason why it’s still so popular today is the mature and performant platform. And because the programs are compiled to the bytecode, the language's deficiencies could be made up for by ... creating other JVM languages.&lt;/p&gt;

&lt;p&gt;To be honest, throughout my career, I’ve used more Groovy, Scala, or Kotlin than pure Java itself!&lt;/p&gt;

&lt;p&gt;So how do those languages look like and how do they compare with each other?&lt;/p&gt;

&lt;h2&gt;
  
  
  Groovy – powerful language and modern syntax
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://groovy-lang.org/"&gt;Groovy&lt;/a&gt; was the first JVM language I’ve learned. I was using it mostly when I was using the Grails framework at my first job.&lt;/p&gt;

&lt;h4&gt;
  
  
  Syntax
&lt;/h4&gt;

&lt;p&gt;What made Groovy stand out was its syntax. On the one side, it eased some of Java language pains via optional semicolons, allowing more than one class per file or type inference with the &lt;code&gt;def&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;On the other hand, it featured modern language features, such as traits, closures, string interpolation, optional chaining (&lt;code&gt;?.&lt;/code&gt; operator) and many other features long before even Java 8 came out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Optional chaining:

def gear = car?.getGearBox()?.getGear()

// Instead of

Gear gear = null;
if (car != null) {
  if (car.getGearBox() != null) {
    gear = car.getGearBox().getGear();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, Groovy is a superset of Java. It means, that a Java class is a perfectly valid Groovy class too! This makes its adoption way easier because you can just change the file extension to &lt;code&gt;.groovy&lt;/code&gt; and transfer it to a more idiomatic code step by step as you need.&lt;/p&gt;

&lt;h4&gt;
  
  
  DSLs
&lt;/h4&gt;

&lt;p&gt;Closures, maps and optional dots and parentheses allows us to create Domain Specific Languages, which can look like almost like written in plain English.&lt;/p&gt;

&lt;p&gt;The excerpt below is from &lt;a href="http://docs.groovy-lang.org/docs/latest/html/documentation/core-domain-specific-languages.html"&gt;the official Groovy documentation&lt;/a&gt; and in my opinion it explains it quite well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show = { println it }
square_root = { Math.sqrt(it) }

def please(action) {
  [the: { what -&amp;gt;
    [of: { n -&amp;gt; action(what(n)) }]
  }]
}

// equivalent to: please(show).the(square_root).of(100)
please show the square_root of 100
// ==&amp;gt; 10.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those DSLs are used for example in Gradle, Jenkins Pipelines, or Spock, so there is a chance, that you’ve been using Groovy without even realizing it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Groovy is a dynamic language, which means, that objects can be modified at runtime via appending methods or intercepting the calls. This is also the reason, why &lt;strong&gt;Groovy isn’t my g0-to language anymore.&lt;/strong&gt; It kind of suffers from the disadvantages of both approaches it tries to merge.&lt;/p&gt;

&lt;p&gt;On one side, it still has to be compiled, because it is run on the JVM platform. Because of that, it can’t benefit from fast feedback loops like in other dynamic languages such as Ruby, which are interpreted.&lt;/p&gt;

&lt;p&gt;On the other one, because it’s a dynamic language, the compilation step won’t give us that much guarantees about program correctness. Even though we can specify types of our variables and method arguments, we still can run into a runtime error at some point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scala – FP and static typing combo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.scala-lang.org/"&gt;Scala&lt;/a&gt; also features some syntax improvements, but way more important is its support for the &lt;strong&gt;functional programming&lt;/strong&gt; paradigm. Immutable objects and lack of side-effects not only make refactoring and testing easier, but it makes Scala well suited for asynchronous programming. Therefore the ecosystem is rich in libraries for that purpose, such as Akka, Monix, Cats, or ZIO.&lt;/p&gt;

&lt;h4&gt;
  
  
  Types
&lt;/h4&gt;

&lt;p&gt;Scala is statically typed, but it is a way more advanced mechanism than in Java. Types are not just classes. The hierarchy is larger, including types such as &lt;code&gt;Any&lt;/code&gt;, &lt;code&gt;AnyVal&lt;/code&gt; or &lt;code&gt;Nothing&lt;/code&gt;. We can also construct types as functions, with defined arguments and returned values. It’s possible to define type aliases to make our definitions shorter and clearer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Class&lt;/strong&gt; is another help in using types in Scala. It’s basically a class with immutable fields and all batteries included. Because the fields are immutable, we don’t have to define getters and methods such as &lt;code&gt;equals&lt;/code&gt; or &lt;code&gt;hashCode&lt;/code&gt; are already there for us. Usually, those classes have just one line of code and they are very convenient to define simple structure types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case class Circle(x: Double, y: Double, radius: Double)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Scala, we also make use of &lt;strong&gt;monad&lt;/strong&gt; types. What monads are is a topic for a completely separate blog post, but what’s important is that they help to make our code more meaningful. We can use &lt;code&gt;Option&lt;/code&gt; if we want to represent a value that may or may not be defined or we can use &lt;code&gt;Try&lt;/code&gt; or &lt;code&gt;Either&lt;/code&gt; if we want to represent a successful result of some operation or an error if it failed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val studentOpt: Option[Student] = students.findById(123)

studentOpt.foreach(student =&amp;gt; println(student.name))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gamechanger here is the fact, that the Scala Standard Library uses those types throughout the library, so we don’t have to worry about null checks or runtime exceptions within the Scala code unless we use them explicitly or integrate with Java libraries using them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern matching and for comprehension
&lt;/h4&gt;

&lt;p&gt;Scala has two particular features, that help to work with monad types and case classes – &lt;strong&gt;pattern matching&lt;/strong&gt; and &lt;strong&gt;for comprehension&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pattern matching seems like a simple switch statement, but it is much more than that. We can define more advanced conditions, especially check types, and use the filtered values without unsafe casting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val result: Either[ErrorCode, SuccessValue] = ???

result match {
    case Right(successValue) =&amp;gt;
      handleSuccess(successValue) // no cast needed, successValue is already of SuccessValue type 

    case Left(errorCode) if errorCode.value &amp;gt; 300 =&amp;gt; // additional conditions are possible too
      handleLowPriorityError(errorCode)

    case Left(errorCode) =&amp;gt;
      handleHighPriortyCode(errorCode)  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For comprehension is the syntactic sugar, which helps us to avoid nested chains of &lt;code&gt;.flatMap&lt;/code&gt; or &lt;code&gt;.foreach&lt;/code&gt; calls when we work with monad types. It’s the easiest to explain it with an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; val employeeNames = for {
  company &amp;lt;- companies
  employee &amp;lt;- company.employees
  if employee.currentlyEmployed
} yield {
  employee.name
}

// is an equivalent of this:

val employeeNames = companies
  .flatMap(company =&amp;gt;
    company.employees
      .withFilter(employee =&amp;gt; employee.currentlyEmployed)
      .map(employee =&amp;gt; employee.name)
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Downsides
&lt;/h4&gt;

&lt;p&gt;The obvious Scala’s downside is a steep learning curve. Due to its complexity, it takes some time to be productive in it and write a proper idiomatic code. In my case, I’ve made the biggest progress during my first code review in a team, which was already using Scala and I think it’s the best way to learn it – from other teammates already proficient in it ;)&lt;/p&gt;

&lt;p&gt;Another issue is that it is similar to C in one specific manner – both of those languages are powerful tools, but because of that, it’s very easy to get carried away and write complicated, unreadable code. It’s part of the reason why Scala’s learning curve is so steep.&lt;/p&gt;

&lt;p&gt;The last one is harder integration with Java libraries. Not being a Java superset could be annoying, but in fact, IDE support makes it negligible. A more serious problem is that Java libraries do not use Scala monad types and they may use mutable objects. Therefore we can receive a null object when we do not expect it, running into a NullPointerException. This is probably one of the reasons why Scala collections were written from scratch and they even don’t implement the &lt;code&gt;java.util.&lt;/code&gt; interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin – a “better Java”
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/"&gt;Kotlin&lt;/a&gt; is the newest of the described languages. Because of that, it had the opportunity to take what’s best from other languages and fix those aspects which were less ok.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nullable types and Java integration
&lt;/h4&gt;

&lt;p&gt;Kotlin’s approach to tackle the NullPointerException problem is to introduce nullable types. When a type is declared with a ? sign at the end (e.g. String?), it means that it can be null. The best part is that it’s the compiler that checks if we try to use such an object without checking if it wasn’t null and returns the error if we did.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val nullableString: String? = null // OK
val notNullableString: String = null // compilation error!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All values coming from Java code are nullable by default, which makes this mechanism work even when we integrate our Kotlin code with some Java library.&lt;/p&gt;

&lt;p&gt;Just like in Scala, we can work with immutable values and collections, but without committing that much to the functional programming paradigm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data classes&lt;/strong&gt; can have mutable fields, where Scala’s &lt;strong&gt;case classes&lt;/strong&gt; can not.&lt;/li&gt;
&lt;li&gt;There are no monad types in the standard library. We can use libraries, like arrow-kt, but we have to wrap the values ourselves.&lt;/li&gt;
&lt;li&gt;No pattern matching, no for comprehension, less complicated (but thus – less expressive) type system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those functionalities make Kotlin a perfect candidate for being a “better Java”. We can see results today, where Android and Spring already have Kotlin integration.&lt;/p&gt;

&lt;h4&gt;
  
  
  Domain Specific Languages
&lt;/h4&gt;

&lt;p&gt;Similarly to Groovy, Kotlin has closures, which lets us build DSL in Kotlin too. The advantage is that in Kotlin such DSLs are &lt;strong&gt;typed&lt;/strong&gt;. Gradle has Kotlin DSL and my IDE can finally check my code for errors and give me some hints about available properties.&lt;/p&gt;

&lt;h4&gt;
  
  
  Coroutines
&lt;/h4&gt;

&lt;p&gt;Closures are also used in another distinct Kotlin feature – &lt;strong&gt;Coroutines&lt;/strong&gt;. In essence, they are simply lightweight threads, which can handle asynchronous operations while preserving the readability.&lt;/p&gt;

&lt;p&gt;The below example comes from &lt;a href="https://kotlinlang.org/docs/reference/coroutines/basics.html"&gt;Kotlin documentation&lt;/a&gt;. If we tried to run 100k of thread at once, we would cause an &lt;code&gt;OutOfMemoryException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.*

fun main() = runBlocking {
    repeat(100_000) { // launch a lot of coroutines
        launch {
            delay(5000L)
            print(".")
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within the coroutine context, the code can be organized with &lt;strong&gt;suspend functions&lt;/strong&gt; , which are functions that are run within the coroutine and its execution can be paused and resumed later, e.g. when the data from the HTTP request arrives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

fun doSomeWork() = runBlocking {
    val result = makeHttpCall()
    println(result)
}

// Simulate making the call and return the result
suspend fun makeHttpCall(): String {
    // The delay here is also a suspend function, which does block the thread.
    // The execution of the makeHttpCall function is paused until
    // the time of delay passes and then it's resumed
    delay(1000)
    return "Some result"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coroutines are pretty heavily used in the web framework called &lt;a href="https://ktor.io/"&gt;Ktor.&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Downsides
&lt;/h4&gt;

&lt;p&gt;Regarding downsides, I think that the biggest one is Kotlin’s young age. I could especially experience it with Kotlin Gradle DSL, where on one hand it’s great that finally the DSL is typed, but on the other hand, it was still easier to copy and paste some Groovy code from the internet than to figure out how to translate it. However, I’m sure, that this situation will be better and better over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other languages
&lt;/h2&gt;

&lt;p&gt;There are of course other JVM languages, but I won’t describe them in such detail, because I haven’t really used them that much.&lt;/p&gt;

&lt;p&gt;The most popular language of this group is Clojure. Just like Scala, it’s a functional language with a steep learning curve. Unlike it, however, it’s a dynamic language and it’s a Lisp implementation. This makes it a very &lt;strong&gt;powerful&lt;/strong&gt; language because the code is also the program’s data and it can be modified. However, in my &lt;strong&gt;subjective&lt;/strong&gt; opinion, this also makes Clojure programs very &lt;strong&gt;unreadable&lt;/strong&gt;. However, a lot of people that influenced me in some way are Clojure users, so maybe I am wrong, therefore I’m not ruling out using it in the future :D&lt;/p&gt;

&lt;p&gt;There are JRuby and Jython, which are basically Ruby and Python implementations on JVM. While using Java libraries in those languages is still possible, they are usually used just as a more performant Ruby or Python interpreter.&lt;/p&gt;

&lt;p&gt;Finally, there is … Java :D I can’t neglect the progress, that Java has made throughout versions 9 to 15 and onwards. New features like &lt;a href="https://openjdk.java.net/projects/amber/LVTIFAQ.html"&gt;type inference with var&lt;/a&gt;, &lt;a href="https://openjdk.java.net/jeps/8213076"&gt;pattern matching&lt;/a&gt;, or &lt;a href="https://openjdk.java.net/jeps/359"&gt;records&lt;/a&gt; definitely sound like a breath of fresh air and a step in the right direction. Unfortunately, I don’t have much experience with that either.&lt;/p&gt;

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

&lt;p&gt;Currently, I’m using Scala at work and Kotlin for my hobby projects.&lt;/p&gt;

&lt;p&gt;Which language would I recommend using?&lt;/p&gt;

&lt;p&gt;I’d choose Scala for data-oriented, asynchronous-heavy applications. That part is pretty well worked out in Scala. There are many libraries for that and functional programming paradigm makes writing such code easier.&lt;/p&gt;

&lt;p&gt;I’d choose Kotlin, for simple applications or the ones which have to be heavily integrated with Java libraries. This is becoming more and more convenient because many Java libraries already started to integrate with Kotlin too.&lt;/p&gt;

&lt;p&gt;Groovy handed to Apache is in my opinion a sign of declining popularity and purpose of this language. However, if you use Java for your production code, I think that Spock alone is a good enough reason to check Groovy out.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konkit.tech/2020/10/25/my-journey-through-jvm-languages/"&gt;My journey through JVM languages&lt;/a&gt; appeared first on &lt;a href="https://konkit.tech"&gt;Konkit's Tech Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>kotlin</category>
      <category>scala</category>
    </item>
    <item>
      <title>What have I learned from speaking at 4Developers 2020 conference?</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Thu, 01 Oct 2020 17:01:18 +0000</pubDate>
      <link>https://forem.com/konkit/what-have-i-learned-from-speaking-at-4developers-2020-conference-57co</link>
      <guid>https://forem.com/konkit/what-have-i-learned-from-speaking-at-4developers-2020-conference-57co</guid>
      <description>&lt;p&gt;At this year’s edition of the 4Developers conference I gave a talk titled “Productivity for Ordinary Developers”. It wasn’t the first time I was speaking at an event, however, there were some new experiences for me anyway. Here are some insights I hope you’ll find interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightning talks are hard
&lt;/h2&gt;

&lt;p&gt;It was the first lightning talk I created and I have to admit – &lt;strong&gt;they are hard&lt;/strong&gt;. Earlier, I was thinking, that if the talk is 3 times shorter, it should be 3 times easier to prepare. The truth is, 15 minutes (or in this case even 12) leave a very little margin. I had to rehearse even harder to make sure, that I’m within the time limit.&lt;/p&gt;

&lt;p&gt;Recording myself training my talk at home was a great help for my preparations. It allowed me to check how the final result would look like. I could watch myself talking, and I could find mistakes or annoyances, which I wasn’t even aware of.&lt;/p&gt;

&lt;p&gt;It also put an element of pressure on me. If I wanted to record a complete try, I couldn’t make any mistakes. Because of that element of mild stress, I could measure the time of my talk more accurately. It also helped me to prepare a schedule for my talk. I played the recording once and noted minute ranges of all major sections of my talk. Thanks to that, I had a cheat sheet, which I could quickly check during the actual talk to instantly know how am I doing with my time. Was I rushing, dragging? Did I have extra time or should I hurry up a bit?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--teoqiEjZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2020/10/4developers-cheatsheet-1024x917.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--teoqiEjZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://konkit.tech/wp-content/uploads/2020/10/4developers-cheatsheet-1024x917.jpg" alt=""&gt;&lt;/a&gt;My cheat sheet :D&lt;/p&gt;

&lt;p&gt;However, it’s extremely important to remember to turn the timer on. Without that, as I unfortunately learned, the cheat sheet is of no use … ! :D&lt;/p&gt;

&lt;h2&gt;
  
  
  Online conferences are … different
&lt;/h2&gt;

&lt;p&gt;This year’s edition was unique because due to the COVID19 pandemic it was a completely online version.&lt;/p&gt;

&lt;p&gt;In terms of technicalities, I think that the 4Developers crew has made a tremendous job. Everything was very well organized, we had rehearsals, where we could learn beforehand how it would look like during the conference. It felt like an appearance in a live TV show :D.&lt;/p&gt;

&lt;p&gt;However, it’s still not the same as the usual on-site event.&lt;/p&gt;

&lt;p&gt;I missed the live audience. Even though the stage fright was a little bit less significant, I really missed that triumph moment between saying “thank you” and the applause from the audience.&lt;/p&gt;

&lt;p&gt;I also missed the networking. A friend of mine once said that he measures how he liked the conference by a number of new connections he has made. This year, there weren’t many occasions to talk to each other.&lt;/p&gt;

&lt;p&gt;I have also watched way fewer talks then I would usually do at an on-site conference. If you are at the venue, where the conference is organized, you usually have a free day at work and there is nothing to distract you from attending the talk and focusing on it. On the other hand, if they are in a form of a broadcast you can watch now or later – there is always something more important to do at home or at work.&lt;/p&gt;

&lt;p&gt;Luckily, the next edition is scheduled on-site :D.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summing up – full success!
&lt;/h2&gt;

&lt;p&gt;I am extremely happy, that in terms of speaking it wasn’t a wasted year for me and I am really grateful for the opportunity to speak at a country-wide conference.&lt;/p&gt;

&lt;p&gt;If you want to see the slides or the “further reading” links, you can find them &lt;a href="https://konkit.tech/productivity/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Why should you use Ruby for your next command-line tool?</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Thu, 18 Jun 2020 21:34:42 +0000</pubDate>
      <link>https://forem.com/konkit/why-should-you-use-ruby-for-your-next-command-line-tool-295d</link>
      <guid>https://forem.com/konkit/why-should-you-use-ruby-for-your-next-command-line-tool-295d</guid>
      <description>&lt;p&gt;One day, I needed to write a command-line tool. It was more complicated than copying a couple of shell commands to a file with &lt;code&gt;.sh&lt;/code&gt; extension, but at the same time it was too simple to make a full Java or Scala application out of it.&lt;/p&gt;

&lt;p&gt;Even though I work mostly with Scala and Typescript, I’ve chosen to do it in Ruby because it’s good for that very purpose – to quickly get your stuff done.&lt;/p&gt;

&lt;p&gt;Here is why:&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD is first-class citizen
&lt;/h2&gt;

&lt;p&gt;Ruby is a dynamic language. That means, that the type of the object is not checked before executing an operation. Objects can be modified at runtime, methods can be added dynamically, etc.&lt;/p&gt;

&lt;p&gt;This sounds like hell for those coming from languages like Java or Scala, but it’s very helpful if you want to do a TDD approach.&lt;/p&gt;

&lt;p&gt;Because there isn’t any compiler to do some checks, proper testing is very important in Ruby. Because of that, there are a lot of tools, which help with that. RSpec lets us write tests with a surprisingly small amount of lines. Nesting lets us reuse the setup between cases, keeping our tests testing only one thing at a time. This makes not only writing, but also reading tests easier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  context('when the rectangle has size 2 x 3') do
    subject { Rectangle.new(2, 3) }

    it 'should return correct area' do
      expect(subject.area).to eq(6)
    end

    it 'should return a correct circumference' do
      expect(subject.circumference).to eq(10)
    end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are lots of other libraries, which we can use alongside RSpec. One example, which I’ve never seen anywhere else is the &lt;a href="https://relishapp.com/vcr/vcr/docs"&gt;vcr&lt;/a&gt; gem. It can be used to record calls to external APIs during tests execution and use cached data on the following runs instead of making the same calls over and over again. The funny thing is, that such things wouldn’t be possible (at least not that easily) if Ruby wasn’t a dynamic language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and community support
&lt;/h2&gt;

&lt;p&gt;Because of Rails popularity, there are Gems (Ruby libraries) for almost everything. Using the work someone once done instead of reinventing the wheel can greatly speed up the development. Also, most of the problems you may face are probably already solved and explained in a Stack Overflow question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object-oriented and High-level API
&lt;/h2&gt;

&lt;p&gt;Ruby’s APIs are simple and with a quite high level of abstraction. For making a command-line tool this is great because we can focus on getting the job done, abstracting the details away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require 'csv'

lines = CSV.readlines("filename.csv")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operations on collections are also syntactically nicer and more familiar to those I know from Scala or Kotlin. I realize, that it’s just a matter of taste, but for me, the intention is clearer this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; [1, 2, 3, 4, 5, 6, 7].select { |number| number &amp;gt; 3 }

 =&amp;gt; [4, 5, 6, 7]

&amp;gt; ["lorem", "ipsum", "dolor"].each_with_index do |word, index|
&amp;gt; puts "#{index+1}. #{word}"
&amp;gt; end

1. lorem
2. ipsum
3. dolor

 =&amp;gt; ["lorem", "ipsum", "dolor"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interpreted language
&lt;/h2&gt;

&lt;p&gt;I’ve mentioned, that Ruby is not a compiled language, thus there is no compiler to check for syntax errors. But what you get in return is instant feedback. You don’t have to wait for your application to compile to see the results.&lt;/p&gt;

&lt;p&gt;This may not sound that convincing – after all, we are developing a simple tool, so the compilation times shouldn’t be that long after all. But on the other hand, you could gain on the faster feedback loop. If your tests run almost instantly, running them automatically each time you change your code suddenly doesn’t sound that insane (check out the &lt;a href="https://github.com/guard/guard-rspec"&gt;guard&lt;/a&gt; gem).&lt;/p&gt;

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

&lt;p&gt;Don’t get me wrong – I don’t want to say, that you should out of the sudden use Ruby for everything. In my current job, we use Scala and I find it an excellent choice for a product developed by a larger team. However for that specific scenario – a simple command-line tool – it might be worth to at least consider Ruby.&lt;/p&gt;

&lt;p&gt;I realize that I may be biased because I’ve been working with the Rails framework in the past. If you are used to other languages such as Python or Go, it may be a good idea to choose them and be productive with tools you already know. However, once in a while, it’s good to expand your horizons and discover what our options do you have.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konkit.tech/2020/06/18/why-should-you-use-ruby-for-your-next-command-line-tool/"&gt;Why should you use Ruby for your next command-line tool?&lt;/a&gt; appeared first on &lt;a href="https://konkit.tech"&gt;Konkit's Tech Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Obvious and not-so-obvious Bash/Zsh terminal shortcuts</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Thu, 21 May 2020 06:43:15 +0000</pubDate>
      <link>https://forem.com/konkit/obvious-and-not-so-obvious-bash-zsh-terminal-shortcuts-3480</link>
      <guid>https://forem.com/konkit/obvious-and-not-so-obvious-bash-zsh-terminal-shortcuts-3480</guid>
      <description>&lt;p&gt;For a very long time, I’ve been using just &lt;code&gt;tab&lt;/code&gt;, &lt;code&gt;ctrl-C&lt;/code&gt;, &lt;code&gt;ctrl-D&lt;/code&gt; and &lt;code&gt;ctrl-R&lt;/code&gt; shortcuts. However, there are more useful gems out there. In this post, I’m going to show you Bash/Zsh terminal shortcuts that I find useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tab
&lt;/h2&gt;

&lt;p&gt;It’s the most important shortcut because it’s the autocompletion. It simply saves you a whole lot of typing. If there is just one possible option, then it will be automatically filled for you. If not, possible options will be presented below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-tab.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-tab.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-C and Ctrl-D – oversimplified explanation
&lt;/h2&gt;

&lt;p&gt;Ctrl-C terminates the currently running command or a process. Ctrl-D is an equivalent of exit command. You can think about the Python REPL, where Ctrl-C ends the currently running command, but Ctrl-D exits the REPL itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-C-ctrl-D.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-C-ctrl-D.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-C and Ctrl-D – a longer explanation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Ctrl-C&lt;/code&gt; sends a &lt;code&gt;SIGINT&lt;/code&gt; signal, to a process, which is currently in the foreground. Application usually interpret this as a signal to kill the process, but they don’t have to do so. This is why Python interpreter doesn’t end the process, but just ends the command that is currently running.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl-D&lt;/code&gt; sends an &lt;code&gt;End-Of-File&lt;/code&gt; marker. To explain this, imagine that we run a Python script. The interpreter reads the program from a file and executes commands until the whole file is read. When it reaches the end of the file, the interpreter terminates.&lt;/p&gt;

&lt;p&gt;When we run the interpreter without any script, our keyboard input is treated as a “file”, from which the commands are read. When we push &lt;code&gt;Ctrl-D&lt;/code&gt;, we inform the interpreter, that it reached the end of the file, all commands are read and thus it can terminate.&lt;/p&gt;

&lt;p&gt;Of course it doesn’t have to be a Python interpreter – the same goes for other interpreted languages or shells like bash. Try to run bash inside a bash – you can “go back” with Ctrl-D shortcut.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-Z and fg command
&lt;/h2&gt;

&lt;p&gt;When you have some long-running command, you don’t necessarily have to terminate it if you have to do something else. When you press &lt;code&gt;Ctrl-Z&lt;/code&gt;, the current process goes to the background. You no longer see its output, but the process is still running.&lt;/p&gt;

&lt;p&gt;If we want to bring back that process to the foreground, we can use the &lt;code&gt;fg&lt;/code&gt; command to do that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-z.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-S and Ctrl-Q
&lt;/h2&gt;

&lt;p&gt;We may also pause the output for a moment. This is useful, when there is a lot of fast-changing output, like application logs we would like to inspect. To pause the output we can use the shortcut &lt;code&gt;Ctrl-S&lt;/code&gt; (like &lt;strong&gt;s&lt;/strong&gt; top). To resume it back, use the &lt;code&gt;Ctrl-Q&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-s-ctrl-q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-s-ctrl-q.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Up and Down Arrows or Ctrl-P and Ctrl-N
&lt;/h2&gt;

&lt;p&gt;To run a previous command, we just need to press the up arrow. With up and down arrows we can navigate between already executed commands.&lt;/p&gt;

&lt;p&gt;The same effect can be achieved using Ctrl-P (like in &lt;strong&gt;p&lt;/strong&gt; revious command) and Ctrl-N (like in &lt;strong&gt;n&lt;/strong&gt; ext command). At first, arrow keys may be more intuitive, but as you become more proficient with keyboard, it may be more efficient to use the latter ones, because you can keep your hands on the letter keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-R
&lt;/h2&gt;

&lt;p&gt;Arrow keys are not convenient to use if the command was executed some time ago. To search in history for a command, we can use a Ctrl-R shortcut.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-R.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-R.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To display whole saved history, we can also use a &lt;code&gt;history&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-A i Ctrl-E
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Ctrl-A&lt;/code&gt; is basically an equivalent of the Home button. It moves the caret to the beginning of the line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-A-ctrl-E.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-A-ctrl-E.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl-E&lt;/code&gt; is like the End button. It moves the caret to the end of a line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-L
&lt;/h2&gt;

&lt;p&gt;To clear the screen and go back on top of our terminal screen, we can use the &lt;code&gt;clear&lt;/code&gt; command, but we can also do it faster, using the &lt;code&gt;Ctrl-L&lt;/code&gt; shortcut. You know – c &lt;strong&gt;L&lt;/strong&gt; ear (not very intuitive, but it’s something …)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-L.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-L.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-W
&lt;/h2&gt;

&lt;p&gt;If we make a mistake in a last written word, we can use this shortcut to quickly delete the last word.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-W.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-W.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-U
&lt;/h2&gt;

&lt;p&gt;When we would like to remove a whole line, we can use &lt;code&gt;Ctrl-U&lt;/code&gt; shortcut (like in &lt;strong&gt;u&lt;/strong&gt; ndo) to clear the whole line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-U.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fterminal-shortcuts-ctrl-U.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-K
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Ctrl-K&lt;/code&gt; shortcut deletes characters from the cursor to the end of the line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ctrl-Y
&lt;/h2&gt;

&lt;p&gt;Now, if we remove a command or its part by either of &lt;code&gt;Ctrl-K&lt;/code&gt;, &lt;code&gt;Ctrl-U&lt;/code&gt; or &lt;code&gt;Ctrl-W&lt;/code&gt; shortcuts, we can paste it via &lt;code&gt;Ctrl-Y&lt;/code&gt; shortcut (like in &lt;strong&gt;y&lt;/strong&gt; ank). It’s very useful when you write a very long command, but then you realize, that you have to run another one first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkonkit.tech%2Fwp-content%2Fuploads%2F2020%2F05%2Fctrl-y.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s it
&lt;/h2&gt;

&lt;p&gt;Did I miss any shortcut that should be on that list? Let me know in the comment!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://konkit.tech/2020/05/21/obvious-and-not-obvious-bash-zsh-terminal-shortcuts/" rel="noopener noreferrer"&gt;Obvious and not-so-obvious Bash/Zsh terminal shortcuts&lt;/a&gt; appeared first on &lt;a href="https://konkit.tech" rel="noopener noreferrer"&gt;Konkit's Tech Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>zsh</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Hi, I'm Łukasz Tenerowicz</title>
      <dc:creator>Łukasz Tenerowicz</dc:creator>
      <pubDate>Tue, 09 May 2017 14:00:05 +0000</pubDate>
      <link>https://forem.com/konkit/hi-im-ukasz-tenerowicz</link>
      <guid>https://forem.com/konkit/hi-im-ukasz-tenerowicz</guid>
      <description>

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