Elixir Data Collection

In Elixir, there are multiple basic data structures to use for storing data collection.

  • List
  • Tuples
  • Dict
    • Keyword List
    • Map

As a newbie, I am not yet feel familiar with them yet as they are use differently compared to when they are used in my previous langauges. Thus, writting a short brief about them is good for me.

List

List in Elixir is a linked list, a very common data structure for every computer science students. It is commonly used in Elixir, as how the array is used in other language. Defining a list can be done by:

1
list = [10, 20, 30, "a", [1, 2, 3]]

As you may know, (linked)list allows only a sequential access to its children. Random access like how you do with array is not available.

Instead, list traversal is done using a head-tail mapping.

1
2
3
4
5
6
7
8
9
10
list = [1, 2, [5, 6]]

[head|tail] = list
# head = 1, tail = [2, [5, 6]]

[head|tail] = tail
# head = 2, tail = [5,6]

[head|tail] = tail
# head = [5, 6], tail = []

Two more basic operations are list concatination and removal.

1
2
3
4
5
6
7
8
9
10
list = [1, 2, 3, 4]

list2 = [10, 11] ++ list
# Faster: list2 = [10, 11, 1, 2, 3, 4]

list3 = list ++ [5, 6, 1]
# Slower: list3  = [1, 2, 3, 4, 5, 6, 1]

list4 = list -- [2, 3]]
# list4 = [1, 4]

The interesting part on these operations are the sequence when the operation is invoked. Concatination is very fast if it happen at the head of the list. On the other hands, it will be slower if it happen at the end of the list, as we need to traverse to there before operating. Adding the item between the list is expensive too. For removal, things happen from the head of the list.

1
2
3
4
5
6
7
8
9
10
list = [1, 2, 3, 4, 1]

list2 = list - [1]
# list2 = [2, 3, 4, 1]

list3 = list - [1, 1]
# list3 = [2, 3, 4]

list4 = list - [1, 1, 1]
# list4 = [2, 3, 4]

Getting the size of the list is also considered expensive as the list is needed to be traversed from the beginning to the end to get the total number of item.

Tuples

For one who studied mathematics in the university, tuples should feel very familair. Tuples is also used to hold a collection. Unlikely to list, tuples uses a continuous memory space to store the data. Thus, random access and calculating length is faster.

1
2
3
tup = {1, 2, 3, 4}
second_item = elem(tup, 1)
# second_item = 2

Keyword List

Keyword list is actually a list of 2-tuples.

The Past 2014 and the New 2015

This is a long time since my last post. I did not discipline myself enough to write often. Anyway, the 2014 was past. This 2015, I promise myself to be more serious.

One of my instructor said “The young guy always looks to the future, while the old guy is looking at the past”. Neither I am old nor young, I feel, this year’s beginning is a chance to look back and forth and she said.

2014

In last year, there are many things happened. Breaking them down by month seems to be the best way to organize, but I can not remember much details. So, I am writing them freely as I could recall.

Working

The biggest thing is that I made another shift: to move from mobile team to the web team at Taskworld. It is almost 2 years that I left web development. There are so many things to catch up. When I first asked to join the new team, I really feel that I will be the one who slow the team down, as other members are the web guys. We decided to make a transition from the old-fashion .NET to Node.js with new technology stack. Not only the time I left from web that makes me worry, but also the new stack that will be used. Not a javascript lover I am, I was not cofident that I can contribute to the team as much as others.

However, the thing that drove me to make a shift is the feeling that if I did not do it, the company would fail. If I did not join, the new team would not be built. Without the new team, we will not be able to competed with others. The first month is pretty hard that I have to learn new stack, and begin to work so quick. The night time is for assignments. Anyway, this is not comparable to the last month of the year that I have to sleep late everydays. Sometime I feel that I push myself too hard, but whenever I think that I have to code for the team, I just can not stop coding.

After the transition, the company asked lot of members to leave as they lack of the things that are necessary to make the company move forward. I invoked with this process. It was a very hard time to assess people and ask them to go. In order to be fair to them, I have to work hard as much as I can to ensure that the team can step to the brighter future. The November and December were so hard for me, good luck that I can endured them and surpassed.

Side project

Bucketlistly is the only side project of the year. We are currently developing the Android version. The bad thing is I pushed less effort on this platform and let’s my friend do lot of jobs. I feel so guilty to him that I can not be much help. It is hard for me to do Android now as my head is filled with iOS and Node.js stuffs. I wish the project could be finished soon. I will give more effort, I promise.

At the end of the year, we got another call from one of the bank in Thailand. However, I am still not sure if we could take this project or not. I myself feel like I want to contribute my 2015 for Taskworld.

Stock trading

I did not perform very well on trading. Anyway, I did learned many lessons.

The above image is that statistic of my trading. KC is the top-gain stock of mine. Talking about KC, the history is very interesting.

Before I bought KC stock, I heard that one of my colleague just made a good income from it. Very soon enough I pinned KC in my favourite list, it was 1.8 baht per volumn, if I could not remember wrong. After waiting for a while (within the next day), the price went up to 1.89 then dropped to 1.86 and kept on its sideway. At that time, I decided to buy the first lot at 1.86. Unluckily, the price was slowly droped for 2-3 steps. As a lacked-of-experience trader, I bought two or three more lots in order to decrease the average price until I got it at 1.74. Nightmare it was, the price then kept dropping again and again… I made up my mind… the price got down to 1.4x. It was unacceptable for me to cut loss at that time. The price went down to the min 1.27. My decision was to withstand, with the belief that the price will rise again someday. I did a good job that I can stand until the price went up to 2.x, and I did make a good profit. However, the thing I learned from KC is that I should cutloss fast, and if I could not do and decided to withstand, then I have to try buying them again at the low price.

I got some profit from small stocks. Thank to the colleague at the work that help pointing them out at the right time. Mill-w2 is the best one, I did trade most at the right time. EE is also good, but I made a same mistake that I didn’t cut-loss again when I bought it on the year end

At the end of the year, my portfolio was not in a good shape. All of the stock I have been holding are the small ones. They dropped drastically at the third week of December according to the dropping of SET index. This time, I learned to trade with set50 derivative. I still on the beginning and hope to make more profit from them.

2015

With the year containing my favourite number ‘15’, I hope that this will be a better year of mine, and I will try my best to make it.

Unluckily that I lost the post I made at the begining of 2014 that I can not compare the goal I aimed for in last year. For this year, I also want to write down the thing I want to achieve.

  • Do more and more exercise. Take a better care of health : I worked hard last year, stay working until a very late at night. This is not good for health. I also have less time for exercise. Thus, in this year, I want to use the time more efficient so that I can sleep earlier and have more time for exercise.

  • Read more books : I think this is the goal I write every years but rarely achieve. Tough, it is still good to jot down. The aim for this year is to read more books that are not a programming related. Let’s wish for 5-6 books.

  • Code more : Not satisfy with myself as always, coding more and more is necessary. I have to do more code kata.

  • Learn at least 3 new programming languages : Now on the list are Elixir, Go and Rust. Also I want to try on of the web framework of each. Meteor.js is anothe framework that catches the interest.

  • Elixir as another main language : After looking at it, I feel that Elixir is another version of Ruby. It makes me feel ease to read and learn. Also, its web frameworks look fine. Thus, I decided that I will put most of my effort with Elixir.

  • Play less game : Let’s say that I should not spend the time with game for more than 10 hours a week. For additional hours, I have to ride a bicycle in the same amout of time. Let’s be strict with the time and measure how much I can make.

  • Use rescue-time seriously : In order to achieve most of the goal, tracking the time usage should be taken as a first class task.

  • Write at least1 blog every 2 weeks : Try writing more if possible.

  • Eat less : Reduce the amount of carbonated drink. 1 can per 2 days. Eat less fat and snack.

  • Do more bike : At least 2 morning and 3 night ride a week. Aim for 2k kilometers ride a year.

  • Get 10% up on stock profit : 10% sounds small compared to what my comrades get. However, this should be a reasonable goal for me this year.

  • Take my mom to foreign country, expected to be Europe – Switzerland : She said she wants to go, I want to make her dream comes true.

Caution on Rebase : How Come That Unexpected Commit?

I love rebase, and has it as a prefered way to ensure that the code is synced between people in my team. Rebase, may be hard for someone, but once you understand its mechanism, it makes a lot of sense and returns to you the beautiful and maintainable code.

Today, I would like to demonstrate one use case when rebase may introduce you the unexpected commit.

Consider this repository:

The feature/webboard branch is not up to date as there is one commit ahead in master branch. By taking the rebase as a sync strategy, you have to update feature/webboard by checking it out, then use git rebase master

Every things look fine. However, you soon realize that the commit 3294a70 is not needed.

Thus, you go back to master branch and do git reset --hard HEAD~1 and have that commit removed successfully.

Again, when the parent branch is changed, you have to rebase your feature branch accordingly. Here, we need to rebase feature/webboard on master.

It is sure that the rebase will be passed without any conflict, as feature/webboard branch is already on top of master. Unless you come back to look at the result tree.

The commit 3294a70 is still there!!! How come!?!?! you already rebase your branch with master. This commit should disappear!

Thing will go worst if you did not take a look at the tree and merge feature/webboard to master right away.

Many people do merging in a reckless manner and then end up having this problem.

Let’s come back to the question. Why does 3294a70 is still there? To answer this, you have to look back on feature/webboard when it is first rebased. As rebase means to reset your branch on to the parent branch, and re-apply the commits in the branch again. Thus, 3294a70 becomes a part of feature/webboard’s commits. When 3294a70 is removed from master, it is still kept by feature/webboard. So when feature/webboard is rebased again, 3294a70 is re-apply as a member of feature/webboard’s commit.

This problem can be solve by carefully watching at the result tree everytimes the rebase occur. It is not hard to spot, and once you spot it, you can simply use git rebase -i to remove such extrac commit.

Remember, git is not hard as long as you know what you are doing and what are going on according to each action. By caring the result of your tree all the time, this problem can be prevented.

My Rule for Stock Trading

I hurt myself from stock trading a lot and think that it is a proper time to set up a rule to ensure that I will not make the same mistake again… if possible.

  1. Set a cut-loss point and strict to it. Let’s make it at 3%.
  2. If the credit is being used, do not buy a big volumn. Instead go on for the smallest portion such as 30k – 40k baht.
  3. Do not buy a big volumn, unless you are very sure about it.
  4. If you buy, then the price drop, do not chase for it. Let’s it go. Cut loss if it reached the point.
  5. Set the point of sell. Sell it when the price reach.
  6. Do not put money on one or two symbols. Buy multiple items.
  7. Make small money often is better than make a big money once (the latter one has higher .. a lot higher risk).
  8. Do not use credit account. Use cash account!
  9. For a small-price stock that is rapidly rising, the price will hit the peak, then go down. At a time it goes down, do not buy it, unless it re-rise again and step over the old peak.
  10. If you buy the stock against the 9. rule and the price continue to go down, do not buy more. Don’t think about buying for getting a lower average price, until you have the idea that it reaches the minimum point of the day.

Quick File Browsing in Vim Using NERDTree

One way to browse the file in Vim is to use NERDTree.

Git Rebase and Its Mechanism

Git rebase is a command that may scare some people. They think that rebase is not necessary. Thus they rarely do rebasing and use only merging. However, I think rebasing is a good practise as it helps you confirm that your branch is working on the latest changes done by others.

What is rebase

Given you are working on a master branch, then there is one feature, say a sign-in, needed to be implemented. What we do here according a normal git workflow is to create a branch named like feature/sign-in. We say that master branch (at commit 94c09e9) is a parent branch of feature/sign-in.

After some commits done on feature/sign-in, suppose you decide to update a base css and make another commit to master

As you may see, the recent update(0d03724) is not yet applied to feature/sign-in branch. feature/sign-in branch is built based on the old master branch at commit 94e09e9.

In order to get a new base (a new commit 0d03724) for feature/sign-in, we need to rebase feature/sign-in on top of master. Thus, rebase, in a simple way, means to change the parent commit of your working branch. Or you can say to rebuild your target branch on top of the base branch.

Rebase can be done by:

  1. Check out your feature branch, git checkout feature/sign-in
  2. Issue rebase command by supplying a new base branch as parameter, git rebase master

After doing so, you will see that the parent commit of feature/sign-in is changed from 94c09e9 to 0d03724.

How does rebase work

Roughly, we see what rebase does is just to move the parent commit of feature/sign-in to the latest commit of master. But what exactly goes on behind the scene?

After rebase command is triggered, these following things happen.

  1. The commits in feature/sign-in are temporarily kept.
  2. The head pointer of feature/sign-in branch is (hard) reset to 0d03724.
  3. The commits in (1) are reapplied consequently. The reapplying results in a new commit which has the same content as the original commit, but with different commit id. For instance, in this scenario, fee8b31 is re-applied and results in fbcaae2. Then, 48efde8 is replied, and results in 781c6c6. If there was any conflict between commit in feature/sign-in and master, the rebase is paused and the developer has to resolve the conflict before using git add <target file> and git rebase --continue.

What to do after rebase

Issueing rebase command, as you may see, causes the commit’s structure of feature/sign-in to change. The rebased feature/sign-in contains a whole new commits 0d03724, fbcaae2 and 781c6c6 compared to the old branch which contains fee8b31 and 48efde8 (noted that fbcaae2 and 781c6c6 are the same as these commits but they got new SHAs).

By getting a new commit structure, you are prevented from pushing to the remote feature/sign-in. The only way to get your updated right there is to use a force push with git push -f origin feature/sign-in. So, you have to make sure that your working branch is updated before doing rebase, or you may end up losing some commits.

When rebase is needed

Rebase is a part of the safe procedure to get your working branch merged into the main branch.

Let’s say we are working on a master branch, there are 2 branches in progress: feature/sign-in and feature/base-layout. The latter feature is finished before feature/sign-in and is merged to master branch.

Soon, you also finished working on feature/sign-in and you want to merge this to master. How will you do?

The easiest way

The easiest way is to merge the code right away by checking out master and run git merge feature/sign-in.

If you were lucky enough, your code would get merged. If not, you have to resolve the conflicts. When merging is finished, you got a new merge commit e9e2b8a which may contain the conflict-resolved content. The good things for this approach are it is easy to understand and the conflict resolving is done only once. However, there are many disadvantages:

  1. Conflict resolving is done only once… yet there may be numerous conflict on numerous files to be resolved.
  2. If there were so many commits on master and merging is done very late, resolving conflicts is a nightmare. You have to call some people who did updates on master and have them help you resolve the conflicts which they may forget what they have done already.
  3. After merging is success, there is no gaurantee that the code will work as normal or the code will pass all the tests available. In a worst case, you need to commit some fix-commits on master to resolve the problem. This is not pleasing.

The rebase-first way

Instead of issuing merge command right away, you should rebase feature/sign-in on top of master first. Without waiting feature/sign-in to be finished, you should oftenly rebase it with master multiple times (the best is to rebase everytime there is a new commit on master).

Two commits (fee8b31 and 48efde8 ) are re-applied and result in efab4e8 and f16eb33 respectively. During the re-apply, if there are conflicts, the rebase is paused and you have to resolve them. In worst case, the rebase is paused for 2 times if both commits introduced the conflicts. After you have the rebase done, you can then merge your code with a no fast forward option using git merge --no-ff feature/sign-in. This merge is no-conflict guarantee.

The key is, as stated above, rebase often, everytime there is a new commit on main branch. This approach helps solving the problem we face on the merge-right-away approach.

  1. The conflict may happen multiples time, but we compare it in a small amount of change. Resolving it is a lot easier because we do it in a bite-size. Also, the changes are still fresh. People can help you solve it easily because they can still remember what they just did.
  2. After rebase, you can test if your code worked normally on your branch without getting master dirty. All fix-commits happen on your branch. master will be clean and easier to maintain.

Do not forget: rebase often, everytime there is a new commit on main branch. This is very important, or this approach will not benefit you much.

Conclusion

Rebase lets you move your working branch on top of the recent version of parent branch. This process helps you update your code and make it perfect for merging. The key is, always rebase everytime there is a new commit on a parent branch. Also do not forget that, rebase cause your commit tree structure to change. Make sure that you got your branch synced before rebasing.

git

My Swift Cookbook

Variable Declaration

Normal Declaration

1
2
3
4
5
6
7
8
9
// Constant
let constantA = "constantA"
let constantA:String = "this is a string"

// Variable
var variableA = "variableA"

// Multiple assignment
var variableB = 0, variableC = 1, variableD = 3.0

Casting

Bridging

Control Flow

Tuple

Function & Closure

Declaration

1
2
3
4
5
6
7
8
9
  func hello(message: String) {}
  func addTen(number: Int) -> Int {}
  func sum(numbers: Int...) -> Int {}

  // Passing function as arguement
  func filter(numbers: [Int], filteringFuntion: Int -> Bool) -> [Int] {}

  // Returning function
  func getTheFunction() -> ([Int] -> Bool)

Class

Declaration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MyClass {

  var myVariable = "text"
  var anotherVariable:String

  init() {
    
  }

  deinit() {

  }

  func hiDude() -> String {
    return "Hi dude!"
  }

  func hiDudeNoReturn() {
    ....
  }

  func hiDudeNoReturnAgain() -> Void {

  }

  func sayMyName(name: String) -> Void {

  }

}

class MyChildClass : MyClass {
  override func hiDude() -> String {

  }
}

Struct

String

A thing that does not make me feel nature here is that String is a Struct. It is a value type, not a reference type. When you pass the string as a method arguement, it’s passed by value. Also, you can not use operator like === with string.

String substitution

1
var text = "this is a \(anotherString)"

Array

Declaration

1
2
3
4
5
6
var array1 = [1,2,3,4]
var array2 = Array<String>()
var array3:[String] = ["aaa", "bbb"]

array1[0...2] = [11,22,33] // array1 = [11,22,33,4]
array1[0..<2] = [55,66] // array1 = [55,66,33,4]

Iteration

1
2
3
4
5
6
7
8
9
var array1 = [1,2,3,4]
for item in array1 {
  item
}

for (index, value) in array1 {
  index
  value
}

Dictionary

Declaration

1
2
3
4
5
6
var dict = [ 
  "key" : "value"
]

var dict2: [String : String]
var dict3: Dictionary<String, String>

Accessing the keys and values

1
2
3
4
5
6
7
var dict = [ 
  "key1" : "value1"
  "key2" : "value2"
]

var keys = Array(dict.keys)
var values = Array(dict.values)

By accessing the dict.keys and dict.values, Swift will try to figure out what type of stuff lying inside the collection. .. This is quite messed for me though, I can’t say var keys:[AnyObject] = Array(dict), swift will force the return value as [String].

Iteration

1
2
3
4
var dict = [ 
  "key1" : "value1"
  "key2" : "value2"
]

Note About Block in Objective-c

Here are some notes about __block in Objective-c.

  • __block is used to make a variable be mutable when used inside a block. Consider this code:
1
2
3
4
5
6
7
NSString* text = "hello";

(void)(^myBlock)() = ^void {
  NSLog(@"Text = %@", text);
};

myblock(); // "Text = hello"

This code print text when the block is called.

1
2
3
4
5
6
7
8
9
NSString* text = "hello";

(void)(^myBlock)() = ^void {
  NSLog(@"Text = %@", text);
};

text = @"good morning";

myblock(); // "Text = hello"

When there is an assignment before the block is called, the changed value does not effect the value remembered in myBlock scope. This is because when myBlock is compiled, text is captured as a constant. Thus, text value is the same no matter how the value of text is changed.

To make the value of text in the block changed, we can do by adding __block identifier.

1
2
3
4
5
6
7
8
9
__block NSString* text = "hello";

(void)(^myBlock)() = ^void {
  NSLog(@"Text = %@", text);
};

text = @"good morning";

myblock(); // "Text = good morning"
  • When debug inside the block, the variables that are not refered inside the block scope can not be inspected (inside the debugging console, by the po command).

Vim Text Selection Trick

I just learned some techniques from my friend today.

Say we have the following text:

1
  NSString* text = [NSString stringWithFormat:@"This is a string %@", self.title];

First trick

If I wanted to do something with the string within “, I can do it easily with Vim using this pattern in command mode.

1
  <c|v|d|y><a|i>[character]

The thing to do first is to move the cursor within the “.

Next, follow the above command pattern.

The first set of command <c|v|d|y> indicates the action you want to perform.

  • c: for making a change
  • v: for selection
  • d: for delete
  • y: for copy

The second set of command <a|i> indicates the scope of selection.

  • a: cover the string between the input character including the input character (“ here).
  • i: cover the string between the input character excluding the input character (“ here).

The last one is the character you want, which is “ here.

Second trick

If you want to select “With” from “stringWithFormat”, you can do it by moving the cursor to “W”, then use [h]. This means, enter visual mode, and make a selection until the first met “h”.

Side trick

To quickly move to “W” in the last question, it’s easily done by using [W]. This means to find the first occurence “W” on the left side of cursor.

Pitfal of Variable Lazy Initialization

Variable lazy initialization is good as it ensures that your variable will not be null. However, there is a pitfall you need to be aware of. Consider the following code that lazily initializes subtaskMenu variable.

1
2
3
4
5
6
- (SubTaskMenuViewController *)subTaskMenu {
  if (!_subTaskMenu) {
    _subTaskMenu = (SubTaskMenuViewController *)self.slidingViewController.underRightViewController;
  }
  return _subTaskMenu;
}

The subTaskMenu is a variable that refers to the view controller on the right panel (ECSlidingView is used to implement the right menu). Can you think of the case that this code will causes a harmful effect? I did not aware of such effect at the time I wrote the code, until it surfaces out.

What will happen if self.slidingViewController.underRightViewController is changed?

Yes, subTaskMenu will point to the old underRightViewController, not the new one. Thus, in this case, you need to add one more condition to check if self.slidingViewController.underRightViewController value is a new one or not as well.

1
2
3
4
5
6
- (SubTaskMenuViewController *)subTaskMenu {
  if (!_subTaskMenu || (![_subTaskMenu isEqual:self.slidingViewController.underRightViewController])) {
    _subTaskMenu = (SubTaskMenuViewController *)self.slidingViewController.underRightViewController;
  }
  return _subTaskMenu;
}