Ruby/Haskell. Hoare's partition sort or quick sort. Imperative or functional approach?

Some of these days I had fun with Haskell. I tried to write Hoare's sort in Haskell. For my implementation I used list's filtering by the element that was in the middle of the list:

qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort xs = partitions (xs !! (div ((length xs) - 1) 2)) xs where
  partitions x' xs' =
    qsort (filter (< x') xs') ++ (filter (== x') xs') ++ qsort (filter (> x') xs')
What is the most interesting that using of this kind of filtering allows to write a more intuitive algorithm than a variant with an imperative implementation. For comparison, below we can see implementations in Ruby.

This is a variant of imperative implementation:

def hoaresort(array, first, last)
  i, j = first, last
  x  = array[(i + j) / 2]

  begin
    i += 1 while array[i] < x
    j -= 1 while array[j] > x

    if i <= j
      array[i], array[j] = array[j], array[i] if i < j
      i += 1
      j -= 1
    end
  end while (i <= j)

  hoaresort(array, i, last) if i < last
  hoaresort(array, first, j) if first < j

  # Uncomment next line if you want to return sorted array as result
  # array
end
And next is a variant of functional implementation:

def hoaresort(array)
  return [] if array.length == 0
  
  x = array[(0 + (array.length - 1)) / 2]
  
  hoaresort(array.filter { |v| v < x }) +
    array.filter { |v| v == x } +
      hoaresort(array.filter { |v| v > x })
end
In my opinion the comparison obviously shows us that the functional approach is more clear and understandable.

curl. Basic authentication

Specify the user name and password to use for server authentication:

curl --user <name>:<password> http://www.test.com
If you simply specify the user name, curl will prompt for a password:

curl --user <name> http://www.test.com
Also you can encrypt name and password before sending your curl request:

curl -H "Authorization: Basic <your_token>" http://www.test.com
where <your_token> is being generated like that:

-ne "<name>:<password>" | base64 --wrap 0

Git. Often used command set

Shows git tree of all commits

git log

Moving around in Git: - destination by:

HEAD^
HEAD^^^
HEAD~
HEAD~3
<branch>^
<branch>~2
<branch>
- or by hash of commit:

fed2da64c0efc5293610bdd892f82a58e8cbc5d8
- commands:

git checkout <destination>
git checkout HEAD~;
git checkout HEAD^2;
git checkout HEAD~2;
git checkout HEAD~^2~2
git branch -f <branch> <destination>
git branch <branch> master^~2
- feature in merge commit

git checkout master^1 # goes to the first ancesstor
git checkout master^2 # goes to the second ancesstor

Creates new feature branch without checking out

git branch <feature-branch-name>
git branch <feature-branch-name> HEAD~

Creates new feature branch and check out

git checkout -b branch <feature-branch-name> HEAD~

Rebasing (target branch ia a current branch)

git rebase <source-branch>
- with hash of commit

git rebase <Commit>
- with interactive mode

git rebase -i HEAD~4
- for rebasing target branch with source branch

git rebase <source-branch> <target-branch>

Reversing changes: - only local

git reset HEAD~1
- for share with remote

git revert HEAD
- only for changing last commit message

git commit --amend

Adds commits (copies) to current branch in given order

git cherry-pick <Commit1>, <Commit2>, ...

Tagging commits

git tag <tag-name>
git describe <place>
OUTPUT: <tag>_<numCommits>_g<hash>

Merging changes (target branch ia a current branch)

git merge <source-branch>

Pulling changes from remote
- in merging way
git pull is equal to git fetch; git merge origin/master

git pull
git push

git fetch
git merge origin/master
git push
- in rebase way
git pull --rebase is equal to git fetch; git rebase origin/master

git pull --rebase
git push

git fetch
git rebase origin/master
git push
- when source is related to remote and destination to local (if branch doesn't exist it will be created)

git pull origin <source>:<destination>
git pull origin foo is equal to git fetch origin foo; git merge origin/foo
git pull origin bar~1:bugFix is equal to git fetch origin bar~1:bugFix; git merge bugFix

- Remote tracking (when some branches can be linked by origin/master independently of master branch)

git checkout -b foo origin/master
git pull

git checkout -b foo origin/master
git commit
git push
- when branch exists

git branch -u origin/master foo
git branch -u origin/master

git branch -u foo o/master
git commit
git push

Pushing changes to remote

git push origin <place>
- source is related to local and destination to remote (if branch doesn't exist it will be created)

git push origin <source>:<destination>
git push origin master^^:foo
git push origin foo:master

Removes foo branch in remote

git push origin :foo

Adds bar branch in local

git fetch origin :bar

openssh. Problem with connection to servers via ssh

One of these days I faced the following problem. I needed to organize the ability to work on two computers with servers via ssh. On one machine a public and private key was generated, a config file was configured, everything worked well. Next, I copied the keys to another machine, also set up config file and verified that the key was added ($ ssh-add -l), but when I was trying to connect to any server I was failing. Both machines were on Ubuntu OS (17.10 and 16.04 LTS).
Next, I tried to test connection:
$ ssh -v your-useful.server.com
Output was next:
...
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC:
 compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC:
 compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
On the last line, the check was froze and ended after a while. After a short searching based on the last line of output, it turned out that problem was associated with a bug in the openssh package. The bug was revealed in the fact that each connection was required to refine the cipher via the -c key.
$ ssh -c aes256-ctr your-useful.server.com
After that, everything began to work. To exclude redundancy, you need to add either in /etc/ssh/ssh_config or in ~/.ssh/config (I chose this option) the following line:
Ciphers aes128-ctr,aes192-ctr,aes256-ctr

Ruby. Null-aware operators

1. The safe navigation operator

There are some languages that support object-oriented programming that have support for the so-called the safe navigation operator (SNO). Also it's known as optional chaining operator, safe call operator or null-conditional operator. The SNO is a binary operator that returns null if its first argument is null;
otherwise it returns the second argument.

It's used to avoid sequential explicit null checks and assignments and replace them with method/property chaining. In programming languages where the navigation operator (e.g. ".") leads to an error if applied to a null object, the safe navigation operator stops the evaluation of a method/field chain and returns null as the value of the chain expression. It's currently supported in languages such as Apache Groovy, Ruby, Swift, C#, Kotlin, CoffeeScript and others. There is currently no common naming convention for this operator, but SNO is the most widely used term.

The main advantage of using this operator is that it solves a problem commonly known as pyramid of doom. Instead of writing multiple nested ifs, programmers can just use usual chaining, but put question mark symbols before dots (or other characters used for chaining).

Ruby supports the &. safe navigation operator (also known as the lonely operator) since version 2.3.0

Let's consider concrete example of using safe navigation operator on Ruby. My current version of Ruby is 2.5.1

Let's say that we have two classes: Owner and Account:

class Owner
  attr_accessor :first_name, :last_name, :age

  def initialize(first_name:, last_name:, age:)
    self.first_name = first_name
    self.last_name = last_name
    self.age = age
  end

  def summary
    "Owner: first name: #{first_name}, last name: #{last_name}, age: #{age}"
  end
end

module Roles
  GUEST = 1
  USER = 2
  ADMIN = 4
end

class Account
  include Roles

  attr_accessor :owner, :role

  def initialize(owner, role = GUEST)
    self.owner = owner
    self.role = role
  end
end

Create instances of these classes like that

owner = Owner.new(
  first_name: 'John',
  last_name: 'Smith',
  age: 30
)

account = Account.new(owner, Roles::USER)

Now we can get a full information about owner from account by the following way

puts account.owner.summary

But what if, while creating instances of our classes, something goes wrong? Then when you try to get the full information about owner from account you won't have guarantees that this operation will be successful. Moreover, we can get an error and our system may fall. Here is an example of such a situation

account = Account.new(nil)
puts account.owner.summary

As result we get next error:

undefined method `summary' for nil:NilClass (NoMethodError)

So, to avoid this, you can use safe navigation operator &.

puts account&.owner&.summary

And instead of an error, we get nil (it's a null in Ruby)

2. The null coalescing operator

The null coalescing operator (called the Logical Defined-Or operator in Perl) is a binary operator that is part of the syntax for a basic conditional expression in several programming languages. While its behavior differs between implementations, the null coalescing operator generally returns the result of its first operand if it exists and isn't null.

In contrast to the ternary conditional if operator used as x ? x : y, but like the binary Elvis operator used as x ?: y, the null coalescing operator is a binary operator and thus evaluates its operands at most once, which is significant if the evaluation of x has side-effects.

In the ruby for these purposes, we can use the operator ||

some_variable = nil || 'default_value'