A Place to Remember


Thoughts, stories and ideas.

Journey to Functional Programming

Dulu, dulu sekali. Saya pernah mencari tentang apa saja hal yang harus saya pelajari agar saya bisa lebih ahli dalam pemrograman Python. Lalu secara tidak sengaja saya menemukan jawaban di stackoverflow yang menyarankan untuk membaca buku Real World Haskell. Di sinilah perjalanan saya menuju Functional Programming dimulai. And the journey begin~

Saya sempat mempelajari Scala di tempat saya bekerja, hanya saja saat itu pekerjaan saya dipindahkan kembali ke pekerjaan yang menggunakan bahasa Python sehingga saya tidak terlalu dalam mempelajari Scala. Dan alasan kenapa saya memilih Haskell daripada Scala dalam mempelajari Functional Programming adalah karena saya sudah cukup lama mengenal Haskell. Saya katakan cukup lama karena antarmuka (Xmonad) di sistem operasi yang saya gunakan dibuat menggunakan Haskell.

Pengalaman pertama saya saat melihat kode-kode Haskell adalah:

  1. Wow!!

  2. Cara bacanya bagaimana ya?

  3. Karakter-karakter aneh apa itu dan apa maksudnya? (.|., !!, ++, >>, $, ::, -->, <+>, ??, |||, etc)

Saya yang terbiasa melihat kode-kode imperative dan OOP sangat pusing saat membaca kode Haskell. Bagaimana bisa sebuah bahasa pemrograman memiliki tingkat pemahaman yang cukup tinggi jika dibandingkan dengan bahasa yang pernah saya pelajari sebelumnya (C/C++, PHP, Python, Ruby, Go, Java, Javascript). Atau mungkin saya hanya belum pernah melihat orang-orang menggunakan karakter-karakter seperti di atas? mungkin saja

Untuk mempelajari Functional Programming saya harus mengubah cara pandang saya tentang bahasa pemrograman. Banyak sekali yang harus saya pelajari seperti apa itu pure function, side effect, lazy evaluation, dan hal-hal baru lainnya. Perjalanan saya masih panjang, semoga saja saya tidak akan menyerah di tengah jalan dan bisa memahami apa itu Functional Programming.

Sebagai penutup, berikut akan saya sertakan kutipan kode haskell yang saya miliki:

myWorkspaces :: [String]
myWorkspaces = clickable . (map dzenEscape) $ [" Base ", " Code ", " Chat ", " Office ", " Graphic ", " Game ", " Other "]
    where clickable l = [ "^ca(1,xdotool key super+"
                        ++ show (n) ++ ")" ++ ws ++ "^ca()" |
                        (i,ws) <- zip [1..] l,
                        let n = i ]

Maven Dependency Problem

I have a problem downloading several pom files from local artifactory. Well, those poms literally doesn’t exist but the jar files are there, so it should not be a problem. The weird thing is it failed to build the package with maven.

So, I create those poms manually. And when I try to build it again:

$  mvn package

The log said:

[WARNING] The POM for “package” is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details

Problem solved, continue to code.


Set Default Browser

For a few month after I did a fresh install of Archlinux, I found that when I try to click a link inside any application, it will call google chrome. So, I decide to fix it today. It actually easy. We can set our default browser with xdg-mime which is owned by xdg-utils.

Requirement

  • xdg-utils

What I did

We can set out default browser with these commands:

$ xdg-mime default firefox.desktop x-scheme-handler/http

And for https:

$ xdg-mime default firefox.desktop x-scheme-handler/https

Create Gif from Video as Project Demo

This time I will show you how to make a gif from a video. Why do we need this? Well, a few hours ago I need to create a demo of a program to get a job. But I can’t give them the source code, that’s why I just show them how the program works.

Requirement

  • Simple Screen Recorder / similar software
  • ffmpeg

What I did

The first thing we need to do is create a video with Simple Screen Recorder / similar software. I make an avi video, but I guess it will work for any kind (but maybe not all kind) of video format. If we use Simple Screen Recorder, we need to specify video input, output format, output location, and frame rate.

The next step is to use ffmpeg to create gif file. Let’s assume that the video is rec.avi and we want to create rec.gif, also we want the gif width to be 800px with the appropriate height. Do not forget to specify the frame rate, this time we will use 15 fps. This is the command I use to create the gif:

ffmpeg -i rec.avi -r 15 -vf scale=800:-1 rec.gif

Now, we can send that gif to show them the demo.


Dive into Sqlite

Introduction

Today we will talk about sqlite in python. I often use mysql as my data source because of a habit, but when I am in a hurry, I guess sqlite will be enough.

To keep in mind:

  • I use python3
  • Sqlite library is called sqlite3
  • I use hashlib to hash the password (not required)

Action

Let’s start with a little bit of code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import hashlib
import sqlite3


con = sqlite3.connect('test.db')

Those import statement is where we put all required libraries. The con variable will handle the connection from / into sqlite database which named “test.db”. Don’t mind the space between import and con, it’s just a habit to give 2 empty line between import statement and code below it.

with con:
    con.row_factory = sqlite3.Row  # this one
    cur = con.cursor()

Now, “this one” is what I prefer because we will get a dictionary when we select some data from sqlite. We can ignore it of course, but the result from our query will be tuple which I do not prefer.

print(data[0], data[1], ..., data[n])

People will not understand what we print unless we tell them.

print(data['id'], data['email'], data['username'], ...)

This one will be more understandable.

“with” statement will handle the resource. We can also handle the resource manually (close the connection) and use try-except to handle the exception.

This is a little code to show how we drop or create table and insert some data into sqlite.

cur.execute("DROP TABLE IF EXISTS users")
cur.execute("CREATE TABLE users (id, email, username, password, authenticated)")
cur.execute("INSERT INTO users VALUES (?, ?, ?, ?, ?)", [1, "petruk@gmail.com", "petruk", hashlib.md5("passwordpetruk".encode()).hexdigest(), True])

cur.execute("SELECT * FROM users WHERE id=?", (1,))
datum = cur.fetchone()
print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))

Now, you can see why I use that row_factory.

Some explanation

  • We drop the table first if the table is exist
  • We create new table which named users. It has several field which is id, email, username, password, and authenticated.
  • We insert a new user into users table.
  • We find a user with a specified id.

To keep in mind:

I use parameterized queries to insert data. Look for it, it will be helpful for your project. I also use hashlib to hash the password. In real case, you should use a better security like bcrypt or others.

The next code will show you how to do batch insert with sqlite. Instead of execute, we can use executemany to insert data.

wayang_actors = (
    (2, "gareng@gmail.com", "gareng", hashlib.md5("passwordgareng".encode()).hexdigest(), True),
    (3, "bagong@gmail.com", "bagong", hashlib.md5("passwordbagong".encode()).hexdigest(), True)
)
cur.executemany("INSERT INTO users VALUES (?, ?, ?, ?, ?)", wayang_actors)

cur.execute("SELECT * FROM users")
data = cur.fetchall()
for datum in data:
    print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))

Now this one is the update query.

cur.execute("UPDATE USERS SET email=? WHERE id=?", ("goreng@gmail.com", 2))
print("Data updated: {}".format(cur.rowcount))

cur.execute("SELECT * FROM users")
data = cur.fetchall()
for datum in data:
    print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))

The complete code is this one.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import hashlib
import sqlite3


con = sqlite3.connect('test.db')

with con:
    con.row_factory = sqlite3.Row
    cur = con.cursor()    

    print("# drop, create table and insert example")
    cur.execute("DROP TABLE IF EXISTS users")
    cur.execute("CREATE TABLE users (id, email, username, password, authenticated)")
    cur.execute("INSERT INTO users VALUES (?, ?, ?, ?, ?)", [1, "petruk@gmail.com", "petruk", hashlib.md5("passwordpetruk".encode()).hexdigest(), True])

    cur.execute("SELECT * FROM users WHERE id=?", (1,))
    datum = cur.fetchone()
    print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))
    print()

    print("# batch insert example")
    wayang_actors = (
        (2, "gareng@gmail.com", "gareng", hashlib.md5("passwordgareng".encode()).hexdigest(), True),
        (3, "bagong@gmail.com", "bagong", hashlib.md5("passwordbagong".encode()).hexdigest(), True)
    )
    cur.executemany("INSERT INTO users VALUES (?, ?, ?, ?, ?)", wayang_actors)

    cur.execute("SELECT * FROM users")
    data = cur.fetchall()
    for datum in data:
        print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))
    print()

    print("# update example")
    cur.execute("UPDATE USERS SET email=? WHERE id=?", ("goreng@gmail.com", 2))
    print("Data updated: {}".format(cur.rowcount))

    cur.execute("SELECT * FROM users")
    data = cur.fetchall()
    for datum in data:
        print("{} {} {} {} {}".format(datum['id'], datum['email'], datum['username'], datum['password'], datum['authenticated']))
    print()