Kotlin scope functions: let, run, with, apply, and also

  • Let
  • inline fun  T.let(block: (T) -> R): R {
      return block(this)
    }
    

    Let returns the result of lambda. Lambda takes as an input parameter the object upon let is invoked. Thus the object can be referred in the function scope as it. The function returns the last statement.

    val test = "my test string"
    val res = test
      .let { it.substring(0, 3) }
      .let { it.length}
    println(res) //3
    

    Let can be used for the null check:

    val test: String? = null
    test?.let {
      println("$it is not null") //prints nothing
    }
    
  • Also
  • inline fun T.also(block: (T) -> Unit): T {
      block(this)
      return this
    }
    

    Also returns the original object and the function invokes the lambda which takes as an input parameter the object which invoked also.

    data class Draft(var id: Long, var name: String)
    val draft = Draft(1L, "test")
    val res = draft.also {
      it.id = 2L
      it.name = "test2"
    }
    println(draft) //Draft(id=2, name=test2)
    println(res == draft) //true
    
  • Run
  • inline fun  T.run(block: T.() -> R): R {
      return block()
    }
    

    Run is an extension function of the object which is invoking run. So in the scope of the function the object can be referred by this (however this can be omitted). The function returns the last statement.

    data class Draft(var id: Long, var name: String)
    val draft = Draft(1L, "test")
    val res = draft.run {
      id = 2L
      name = "test2"
      name
    }
    println(draft) //Draft(id=2, name=test2)
    println(res) //test2
    

    Run can be used for the null check:

    val draft: Draft? = null
    draft?.run {
      println(draft) //prints nothing
    }
    
  • Apply
  • inline fun T.apply(block: T.() -> Unit): T {
      block()
      return this
    }
    

    Apply is an extension function of the object which is invoking apply. In the scope of the function the object can be referred by this. Apply returns the original object.

    data class Draft(var id: Long, var name: String)
    val draft = Draft(1L, "test")
    val res = draft.apply {
      id = 2L
      name = "test2"
    }
    println(draft) //Draft(id=2, name=test2)
    println(res == draft) //true
    
  • With
  • inline fun  with(receiver: T, block: T.() -> R): R {
      return receiver.block()
    }
    

    With is invoked with the object passed as an argument then an extension function is called on it. In the scope of the function the object can be referred by this. The last expression of with function returns a result.

    data class Draft(var id: Long, var name: String)
    val draft = Draft(1L, "test")
    val res = with(draft) {
      id = 2L
      name = "test2"
      id
    }
    println(draft) //Draft(id=2, name=test2)
    println(res) //2
    

Please find the link to the Kotlin documentation regarding the conventions of using the scope functions.

Advent of code 2017 in TypeScript

Mission completed! I have just solved the advent of code 2017, however in June/July 2019 and not in December 2017 🙂
Programming puzzles can be found here: adventofcode2017 and my solutions: github/rzubala.
This time I used TypeScript which I was only using before for Angular applications development. I was just curious about the possibilities of this language in solving sometimes advent of code’s complex numeric problems. And indeed TypeScript is very handy, easy and fast to develop the code language. I would even say that sometimes it was easier to solve the puzzle in TypeScript than in Python I was using before.

Ubuntu – old releases

When you are using non-LTS Ubuntu your system may become impossible to update very soon. When the system upgrading is not the option you could try to update the content of
/etc/apt/sources.list
as follows:
s/archive.ubuntu.com\|security.ubuntu.com/old-releases.ubuntu.com/g

Mutt as an command line ImapFilter

I have a free email account on wp.pl server and I use it as a secondary account only for shopping or registration purposes. Everything works just fine and the only issue is the SPAM which wp.pl sends me everyday and this SPAM can not be filtered by the filters defined in the account settings. I am fine with this since I am not paying for anything and it looks like it’s just the price you need to pay for this account.

I have started to look for some command line tool in order to filter and remove these unwanted and annoying messages automatically. I found a tool named ImapFilter. You can define some rules how to deal with the messages and ImapFilter will do everything by itself. The configuration is pretty simple:
Screenshot from 2018-09-10 16-20-29

… however in my case I was not able to make it running, I was playing around with the settings but every time I was receiving an error like that:

$ imapfilter
imapfilter: reading data through SSL; EOF in violation of the protocol

So I decided to look for an alternative solution and eventually I found a command line email client Mutt. It’s really powerful and handy utility and without any issues I was able to make it running and apply SPAM filtering.

The configuration is stored in ~/.muttrc file:

set imap_user = "someaccount@wp.pl"
set imap_pass = "somepassword"
set smtp_url = "smtps://someaccount@wp.pl@smtp.wp.pl:465/"
set smtp_pass = "somepassword"
set from = "someaccount@wp.pl"
set realname = "AA"
set folder = "imaps://imap.wp.pl:993"
set spoolfile = "+INBOX"
set header_cache=~/.mutt/cache/headers
set message_cachedir=~/.cache/mutt/messages
set certificate_file=~/.mutt/certificates
set move = no

To show the messages in Mutt sent by wp@wp.pl one need to define the limit ~f wp@wp.pl. Then to delete the messages one need to press D and confirm the operation with the key $. And that’s it.

To make it even faster I defined an alias in ~/.bashrc file:

alias wppl='mutt -e "push '"'"'<limit>~f wp@wp.pl<enter>D<enter>'"'"'"'

which opens the mutt with already filtered and tagged to delete messages.