2018年1月5日 星期五

Erlang快速開始

那麼今天就來介紹說很久但是一直沒有寫的Erlang吧!
Erlang是一隻很有趣的語言,它絕對跟你看過的主流語言有巨大的差異,無論是語法上還是思想上皆是如此

首先我們需要安裝環境,請參考官方的Downloads
接著我們就從erl開始吧
$ erl
輸入指令啟動Erlang的互動環境
你可以先嘗試輸入
1> X=0.
0
2> X=1.
** exception error: no match of right hand side value 1
為什麼會出現例外呢?因為Erlang不準改變變數之值,Erlang將X=0.這樣的述句稱為綁定,而變數一但綁定就不能再次綁定,所以X將永遠為0,請不要害怕這會成為問題
事實上,在共時編程中,這樣的結果是令人安心的,競態問題將大幅減少,你將得到的是助益
那麼我們來看更加細節的部份,首先變數名稱並不是能隨意命名的,在Erlang中,只有大寫開頭的名稱會被當成變數名稱,因為小寫被原子(atom)佔去了(小寫開頭即為原子,後面再解釋何為原子)
綁定只有一次,.是一個述句的結束

接著我們來看更多的案例
3> X + 20.
20
就是個加法

4> 0 = X.
0
5> 1 = X.
** exception error: no match of right hand side value 0
和剛才稍有不同,不過你可以從這個案例看出為什麼叫做綁定,因為這是雙向的,=會比較兩邊是否相同,如果左值尚未被綁定就會進行綁定行為
8> X = 1-1.
0
這裡有更有趣的案例,你可以更清楚的了解到=的行為

9> 4/2.
2.0
10> 3/2.
1.5
11> 1/3.
0.3333333333333333
這裡可以看到Erlang對數字型別的自動轉換,運算在Erlang中相當輕鬆,Erlang已處理了最麻煩的部份

17> hello.
hello
原子之值即自己
18> O = {0, 0}. 
{0,0}
元組(tuple)可以想成匿名的C結構

由於神奇的模式綁定(其實就是=的規則),我們可以寫出如
19> Me = {person, {name, "Danny"}, {height, 160}, {sex, male}}.
{person,{name,"Danny"},{height,160},{sex,male}}
20> {person, {name, MyName}, _ , _} = Me.                         
{person,{name,"Danny"},{height,160},{sex,male}}
21> MyName.
"Danny"
這樣複雜的對應式,_匹配任意值但是我們不care那是什麼,可以看到我們透過綁定取得MyName,話說我是不是寫太矮了(咦)
這裡也展示Erlang常用的技巧,利用atom標記欄位
需要注意的是如果右值具有不存在的參考,Erlang會說明此參考尚未繫結(unbound)
22> C = A.
* 1: variable 'A' is unbound
就像這樣

列表(list)
24> A = [1, 2, 3].
[1,2,3]
25> [F, _, _] = A.
[1,2,3]
26> F.
1
可以看到列表與結構皆能做模式比對

差別在於這個案例
30> [H|T] = A.
[1,2,3]
31> H.
1
32> T.
[2,3]
你可以透過特殊的語法比對出Head與Tail,熟悉函數式編程的同學應該已經興奮不已了吧,大概啦
這個特性讓list能夠被迭代,而tuple不能

接著我們來談字串
35> Name = "Hello".
"Hello"
36> Name.          
"Hello"
看起來與你過去所學無異,但其實Erlang是用數字列表代表字串的,所以你可以
37> [83, 117, 114, 112, 114, 105, 115, 101].
"Surprise"
這真的很Surprise
但是如果列表無法組成字串,就只是普通的列表,算是Erlang中最難搞的陷阱之一

最後教你怎麼退出erl
輸入q().
38> q().
ok
39>
像這樣,這會頓一下才退出

你也可以按<C-c>,輸入a,按<Enter> (a)bort
1> 
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a
像這樣

按<C-g>,輸入q,按<Enter>
1> 
User switch command
 --> q
像這樣

輸入halt().
1> halt().
像這樣,這會馬上退出

下一篇介紹模組好了,我到底欠幾個下一篇了QQ

2018年1月1日 星期一

Refactor Redux-go

如標題所示,這次我要談論的是redux-go重構
在幾次的測試撰寫過程中,我發現舊版的redux-go有一些小問題
首先是Action物件建構不易,且無關的資訊不斷出現
何謂建構不易?我們必須用
redux.SendAction("type")
這樣彆扭的寫法來建構只有typeAction
然而需要Args時,卻要使用
&redux.Action{
    Type: "type",
    Args: map[string]interface{} {
        // ...
    },
}
這樣複雜的寫法,直接使用struct非常容易出錯,如果客戶端直接插值給Args,結果只會是panic
讓介面容易被使用,不容易被誤用
而且redux這個模組資訊完全是非必要的,所以我在v0.5.0將整個Action部份移到redux/action模組
這樣一來程式就變成了
import "github.com/dannypsnl/redux/action"

action.New("type")
非必要的資訊已被移除,現在我們可以專注於action
下一步是讓新增Args的介面容易使用,所以我在v0.5.1新增func (*Action) Arg(string, interface{})方法進入action模組
於是新增Args變成
action.New("type").
    Arg("key", value).
    Arg("key2", value)
這樣的流暢呼叫式

第二個部份是Store,大抵和Action問題一樣,所以亦將其移入store模組
所以客戶端程式就變成了
import "github.com/dannypsnl/redux/store"
import "github.com/dannypsnl/redux/action"

func main() {
    store := store.New(reducer...)
    store.Dispatch(
        action.New("type").
            Arg("key", value).
            Arg("key2", value))
}
注意省略概念外的程式

第三是DispatchC方法的部份(屬於Store)
原本我發現在效能較高的電腦上,序列式的計算subscribed function比共時化的程式更快
於是分成兩個API
但是經過檢討,我認為這只會造成困惑,且未來多核心能力上升,Go亦可能優化其排程器使實作更加高效,比起讓客戶端負擔測試程式效能的成本,直接採取共時版本的實作更加適合,因此採取這個作法(v0.6.0)

經過這次重構,我重新認識了Go的模組組織概念,還有誰來負擔決策成本的問題,是非常有趣的體驗

2017年12月24日 星期日

Getting Start in Go -- part 1

Many people want to learn Go. But how to start? That is a big problem.
Maybe you already heard a lot like: Go is good at concurrency with go-routine, channel brabrabra, but I think those things won't be most important things in Go.

I think the most important thing in Go is: Simple. Keep this in mind.
Why did I say that? Think about
public static void main(String[] Args)
Should we really need such like this?
With a link, I hope you can rethink the problem.
That twitter shows an unreadable error message from C++ compiler.
Why simple is the point, consider python. How quick is its development?
So I will tell you some good part of Go. And what's are you should avoid.

@ package system
import (
    "os"
    "fmt"
)
import something in Go is simple. Just with some string, but what rule them use?
It managed by path.
You need to set $GOPATH in your system at the beginning. And install process should set a $GOROOT, and they are the package location.
For example, if you have a GitHub project.
You should place it under: $GOPATH/src/github.com/your-account/project
[Good part]: In fact, because of mapping rule about domain & Go package system. We can help different people run up the project, without complex setting script(as you can see in C++ project, and more language can have)
ps. This benefit also on npm, cargo, nimble these package manager with a good package dependencies document.
Whatever, that is the way how Go deal with this problem.
After import, you will get a package name, that is final stuff of the path string
For example, import "github.com/dannypsnl/redux" will get redux.(My GitHub project, XD)
[Good part]: If you don't like the project name(maybe that is too long), or both packages have the same name, you can rename it.
import (
    "os"
    "fmt"
    rdx "github.com/dannypsnl/redux"
)
In this case, you will get rdx, instead of redux.

[Bad part]: Now, the problem comes, if you need to use a certain version of a package, but another project depended on another version of this package. How to solve it?
In fact, we don't have a good solution, it's also is the biggest problem in Go.
My way is to make sure the package I am using is using git to do version control.
Then write a build script for my project, check out the correct tag I want to use.
Not perfect, but work.

@ Variable
In Go, we have four-way to define a var.
func main() {
    var a int
    var a int = 1
    var a = 1
    a := 1
}
[!Warning]: you can not declared a four time in actual program.
1. define without an initializer, then go will init it for you.
2. define var with type and initializer
3. only initializer
4. short def
[Important]: short def can only using in function
[Good part]: I prefer to use short define in function, that is like python. And the better thing is you know that is definition or assignment.
[Bad part]: First way have a problem, in user-defined type, it usually work not good.
My suggestion doesn't use it.
The Second way is not good when the type can be easy for sure. But useful when it doesn't.
Third way useful when the type can easy to sure.

@ Loop
Go only have a loop syntax, that is "for".
> forever: 
for {
    // statements
}
Just without any condition.
> traditional for:
for i:=0; i<10; i++ {
    // statements
}
As you can find in C. [Important]: i++ is a statement, cannot be expression
> enumerate loop:
list := []int{ 1, 2, 3 }
for i, v := range list {
    // statements
}
i is index, v is value of list
If you enumerate map, then that will be key, value.
> while loop:
for ;$condition; {
    // statements
}
Put condition(i < 10) only is while loop.

@ gofmt
Go required the same format of the file.
[Good part]: Easy to find out the syntax error. The team works become easier at here.
[Bad part]: Maybe you just hate being controlled.

I will talk about others things next time. See you.

2017年12月23日 星期六

Type driven development -- by C++

Let's start from some code. And seems will be only code in this article.
// Compile: clang++ main.cc
#include <iostream>

template <int x, int y> class Matrix {
  // We don't care how to implement at here
public:
  std::string print() { return std::string("Matrix"); }
};

template <int x, int y> Matrix<x, y> Add(Matrix<x, y> a, Matrix<x, y> b) {
  return a; // Just help compile can run it.
}

int main() {
  std::cout << Add(Matrix<2, 2>(), Matrix<2, 2>()).print() << std::endl;
  // This line never pass, interesting part.
  std::cout << Add(Matrix<3, 2>(), Matrix<2, 3>()).print() << std::endl;
}
Ok, some code be there, why I want to talk about these code?
Few weeks ago, I study Idris and it's core concept: Type-Driven-Development.
But what is TDD(T is Not test at here)?

Matrix can show this concept clearly. Because we need some meta to make sure we are adding correctness Matrix together.
We don't want something like [0 0] + [1 0 3] can work, because Matrix can't be that.
So what will we do at first? Every programmer will check it(I thought, hope I am correct). And most of them will check it at: runtime. But runtime checking is danger. If I could, I always trying compile-time checking, because the chance that can be find out by editor is very big, almost 100%. But how to do that?

In C++, template help we checking at compile-time.
And almost no other language can template integer as template parameter. In Java, we have generic only. And a lot language only have generic too.
But maybe some people can't understand idris, so let's use C++.

The point is: when we need Matrix add. Only those Matrix with correct X, Y can add together.
With template check, second Add always can't pass compile.
Hope you already got the point of TDD.
That is  define type for certain usage, you can get the help from Type System.
It can limit error into a narrow part.
Thanks for read.

2017年12月17日 星期日

Generic with Go?

Hi, I found I had talk about Go with generic have a problem. And it caused by interface{}
Of course, interface is a powerful tool in Go. We can use it as contract to make sure some references must have some method.
But this concept could have some problem when it work with generic.
Consider this:
func X<T>(obj T) T {
    // impl
}
func X<Writer>(obj Writer) string {
    // impl has a little different with common T
}
It seems normal, we need specialize some generic for special type, right?
But the problem coming, Writer is a interface, so anything have Write(assume) method, will fall into this X, it's very awkward. We could accept we will execute the normal version.
Out of expected might be almost the worst thing in computer programming.

I have to say all trick can solve it is not good.
But if drop interface, it will be panic, and I also didn't think that will be good.
I have some suggests, don't specialize interface type, if you can.
If you use anything implement by generic, testing the use case you have to make sure it work as expected.

So just these, writing Go is a interesting trivial.

2017年12月10日 星期日

React with Redux -- todo list

Everyone know todo list is a good practice at front-end programming.
I also create one, and notes some interesting points.
Let's start it.
First, download create-react-app by npm.
$ npm i -g create-react-app
Then use it create a new project `react-todo`
$ create-react-app react-todo
Waiting few seconds. Then you will see a directory call `react-todo` at there.
Ok, `cd src/` then you can find App.js.
We don't deal other things. Focus on todo list. So let's insert some html in App component!
<ul>
  <li>todo 1</li>
  <li>todo 2</li>
  <li>todo 3</li>
</ul>
You can see the result by execute `npm start`.
I usually use two checker. `flow` & `npm test`. `npm test` is provided by create-react-app. It using jest(when I write this).
And `flow` is a type checker. It can check type for you, and best thing is you can choose you want to use it or not, by adding comment at the file's head:
/*
@flow
*/
to open, or close it by no adding these.
Ok, so now we know this part is todo-list. Good, I use component TodoList instead of hard code at here first.
<TodoList />
$ mkdir TodoList/ && cd TodoList/ && touch index.js
Then `import TodoList from './TodoList'` to get component.
It doesn't hard. Next we that TodoList can work.
class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      todos: [], // string[]
      todoStr: "" // string
    }
  }
  // evt of nextTodo is Input Element's event, listen to OnChange
  nextTodo = (evt) => {
    this.setState({
      todoStr: evt.target.value
    });
  };
  // evt of addTodo is button Element's event, listen to OnClick
  addTodo = (evt) => {
    this.setState({
      todos: [...this.state.todos, this.state.todoStr]
    })
  }
  render = () => (
    <div>
      <input value={this.state.todoStr} onChange={this.nextTodo}/>
      <button onClick={this.addTodo}>Add Todo</button>
      <ul>{
        this.state.todos.map((todo, index) => <li key={index}>{todo}</li>)
      }</ul>
    </div>
  )
}
It works. Then you can trying to spread out Todo Component, if you need a more complex Todo component.
Then we go to see redux.
import { createStore } from "redux";

type TodoAction = {
  type: string,
  index?: number,
  todoStr?: string
};

const todocer = (state: string[] = [], action: TodoAction) => {
  switch (action.type) {
    case "ADD_TODO":
      return [...state, action.todoStr];
    case "DELETE_TODO":
      return state.filter((todo, index) => index !== action.index);
    default:
      return state;
  }
};

export default createStore(todocer);
It's a little bit complex, because I use flow in the example here, but still, you can see we are doing the same things. But we move TodoList's data structure management from TodoList component to our reducer todocer. Why we have to do this? Because I want to talk about redux? I am joking. The truth is if our project grow, and other part depends on todo-list's status to decide what should them do. In traditional way, we will go to a hell about data dependencies, a ref b, b ref c... And finally, infinite task be created, but you almost can not find out the begin of this chaos.
Redux didn't solve the problem, but it that flow of data changing is visible & traceable,
so on we can find out the problem instead of rewrite it! Oh! I forgot everyone rewrite front-end every six months. Good!
Next we use Provider connect react & redux, you can without it! That's true, I usually use import store from 'path/to/store' to manage access, but today let's use react-redux.
import { Provider } from "react-redux";
import store from "path/to/store";

<Provider store={store}>
  <App />
</Provider>
This is how we use react-redux, it will send store by context to every child component.
So you will get the right to access the store you put into Provider by
this.context.store
ps. I don't want to talk about redux's API, you can google it.
I think this trick cause some problem, we have to import a lot of thing when testing, and that is boring. And connect function is too complex to hard to learn how to use. Of course, once you got the point, that will be easy.
Today's article end at here, thanks for read.




Ok

2017年12月4日 星期一

Go binding llvm

Use command
$ go get -d llvm.org/llvm/bindings/go/llvm
to get llvm project
Then
$ cd $GOPATH/src/llvm.org/llvm/bindings/go/llvm 
Then
$ mkdir workdir && cd workdir && mkdir llvm-build
Then go back to dir go/llvm
$ ./build.sh -DCMAKE_BUILD_TYPE=Release
I had installed Ninja, then build script use it to build system.
I am not sure if you didn't install it, can compile or not.(Maybe will invoke make)

After those steps.
You can create a main.go
package main

import (
    "fmt"
    "llvm.org/llvm/bindings/go/llvm"
)

func main() {
    m := llvm.NewModule("hello")
    fmt.Println(m)
}
Then go run the main file.
You will see some LLVM IR
It contains module information.
Thanks for see.