2015年3月21日 星期六

使用Vundle 維護的新vim 設定

離上一篇「我的vim設定」已經過了一段時間
http://yodalee.blogspot.tw/2012/09/vim.html
其實這個設定已經過時,大約去年九月左右就已經整個換掉了。

現在的設定是由阿蹦大神推薦的,包括:
* Vundle: https://github.com/gmarik/Vundle.vim
自動安裝插件的插件
* ultisnips: https://github.com/SirVer/ultisnips
強大的原始碼片段展開
* vim-snippets: https://github.com/honza/vim-snippets
各種snippets的集合
* YouCompleteMe: https://github.com/Valloric/YouCompleteMe
補齊插件,包括C語言、Java(雖然我沒寫)跟python 的補齊
* Cscope: https://github.com/steffanc/cscopemaps.vim
Cscope,利用Ctags 幫助原始碼查找的工具
* vim-better-whitespace: https://github.com/ntpeters/vim-better-whitespace
vim-better-whitespace,自動幫你把trailing whitespace 給幹掉的插件

另外還有一個,不過這不是很重要(=w=)
Rust.vim: https://github.com/rust-lang/rust.vim

用上Vundle 的好處是,安裝plugin 變得簡單很多,不像以前要用dropbox同步所有設定檔,同時Vundle 可以透過github 安裝,能直接update plugin,像我剛裝的時候還沒有Rustlang 的snippets,後來update 一下就有了。

設定:

首先設定Vundle,照著Vundle 的設定打就行了,先用git 把Vundle.vim 載到~/.vim/bundle 資料
夾裡:
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

然後在設定檔加入
filetype off
set runtimepath+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'
Plugin 'SirVer/ultisnips'
Plugin 'honza/vim-snippets'
Plugin 'Valloric/YouCompleteMe'
Plugin 'steffanc/cscopemaps'
Plugin 'wting/rust.vim'
Plugin 'ntpeters/vim-better-whitespace'
call vundle#end()
想要裝的plugin就像這樣,在vimrc 裡面插入Plugin,後接git repository 的url 或是author/pluginname;接著在vim 裡面下達:PluginInstall 讓Vundle 猛攪一陣就可以了。
再來是設定其他兩個plugin
首先是Ultisnips,這個比較簡單,因為我們vim-snippets 裡的檔案會存在
.vim/bundle/vim-snippets
裡面;另外是觸發snippet 的按鍵,設定Ultisnips的參數,xxxxxxx請改自己的家目錄:
let g:UltiSnipsSnippetsDir=["/home/xxxxxxx/.vim/bundle/vim-snippets/UltiSnips"]
let g:UltiSnipsExpandTrigger="<c-j>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"

youcompleteme比較麻煩,在C語言系統它要先編過一些東西,先設定vimrc:
let g:ycm_global_ycm_extra_conf = '/home/xxxxxxx/.vim/plugin/.ycm_extra_conf.py'
let g:ycm_extra_conf_vim_data = ['&filetype']
上面這個.ycm_extra_conf.py可以在.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/
裡面找到(講到這裡我就要靠北一下,我記得這個py檔不設定的話YouCompleteMe會跟我一直叫叫叫,然後一堆人都遇到這個問題丟去github 上問,作者只會回「去看文件」啊你文件就沒有講吼!)
這裡面是YouCompleteMe 的設定檔,我只有把裡面的 -Wc++98-compat 改成 -Wno-c++98-compat,使用一些 C++11 的語法時才不會一直警告和 C++98不相容。

然後YouCompleteMe需要編譯,需要安裝編譯工具、Cmake跟python-dev,然後:
cd ~/.vim/bundle/YouCompleteMe
./install.sh --clang-completer

Cscope的話,首先要安裝ctags 跟cscope,在Linux 用套件管理程式都可以安裝。
接著在原始碼根目錄的地方,先用ctags -R 產生tag 檔,之後打開vim後,在關鍵字上使用Ctrl + ] 就可以進行跳躍,用Ctrl + t跳回。

大概就是這樣,現在你的Vim 應該已經變成相當強大的工具了,Happy Vim。

2015年3月1日 星期日

Rust Pointer, Ownership and Lifetime:


這篇主要參考是:
http://slides.com/liigo/rust-memory/fullscreen#/

前言:

pointer是語言上一種常見的實作方法,也是C/Cpp常見的寫法,讓你可以利用指標對資料(某塊記憶體)進行操作,達到極高的操控性。
問題是什麼呢?Pointer 讓你直接操控一塊記憶體,相對的,它也會造成空的指標,雙重釋放、未釋放記憶體等不安全(這裡的安全是指不正常的使用指標,造成memory leak)的操作;兩個指標可以指向同一塊記憶體,在多執行緖裡造成race condition(競態條件)。

我們既需要pointer 所帶來的彈性,又不希望pointer 和不正常使用帶來的不安全。

同時當系統愈來愈大,加上更多平行化機制之後,要求設計師對每塊宣告的記憶體負責愈顯得不切實際,作為下一代的語言實在不該讓程式莫名的存取到不該用的記憶體,讓作業系統丟出seg fault 把程式切掉(引用:AZ大神)。
類似的問題與回應在Cpp也看得到(我真懷疑Cpp到底有什麼概念沒實作的XDDDD),像是 C++11引入的smart pointer, shared pointer,都是針對這個問題而來。

Rust 使用的解法是:定義了Rust Ownership跟Lifetime規則,直接限制pointer 的傳遞、複製、刪除,由編譯器在編譯時即進行檢查(老實說還滿嚴格的 Jizz),避免不正當的pointer 使用方式,來兼顧安全與控制;同時排除掉執行期的檢查成本。
相對於golang,使用的是garbage collection 的方式來處理資源釋放的問題,Rust 連garbage collection 都不要有,一但你的資源(memory) 生命期結束,編譯器就自動幫你把資源釋放掉。

Pointer, Ownership, Lifetime: 

首先我們先介紹Rust 的pointer,主要有兩種型式,一種是直接的Reference,就跟C/C++一樣,可以用 & 或是 ref 取另一個變數的位址;另一種則是box pointer,跟C/C++的malloc 一樣,它會分配heap 區內的記憶體給這個pointer,使用方法請見:
Ref pointer: http://rustbyexample.com/flow_control/match/destructuring/destructure_pointers.html
Box: http://rustbyexample.com/box.html

我們這裡提到兩個名詞:持有權(Ownership)跟生命期(Lifetime),就來做細部介紹:

Ownership指的是一個pointer 對某塊記憶體的持有權。
例如在ownership guide 裡的例子,在一個scope 裡面malloc/free 一塊記憶體,在Rust 裡就是直接宣告let x = box; Rust compiler 會幫你放掉這塊記憶體。
所有的資源都只能有一個持有者,擁有持有權的pointer 可以將pointer 轉送(Move)或借給(Borrow)其他人,例如把它傳送到函數裡面,當我們把pointer 當做函數的argument時,資源擁有權就轉走了。
例如當我們用box pointer:也就是C裡面的malloc/free 型態的pointer,傳送到function 裡的時候,在caller 的變數即無法再存取這塊資料,在函式的末端,這個資源的持有權無人承接,系統就將它釋放掉,就像這樣:
fn main() {
  let x = Box::new(5);
  add_one(x);
  println!("{}", x);
}

fn add_one(mut num: Box<i32>) {
  *num += 1;
}
上面的println 會出現compile error,因為資源已經轉手給add_one,並在add_one 的末端被釋放掉,由於main裡的pointer 已經無法再存取那塊記憶體,由此杜絕存取dangling pointer 的可能性。

如果要再使用這塊記憶體,就要在函數末端將它的擁有權傳回來
fn add_one(mut num: Box<i32>) -> Box<i32> {
  *num += 1;
  num
}
這個寫法相當常見,在Rust 裡可以用ref 的寫法來代替,這在文件內稱為借用(Borrowing),就像這樣:
fn add_one(num: &mut i32) {
  *num += 1;
}
那Lifetime呢?在Rust 裡每個變數都有它的Lifetime,一般來說Rust compile 會幫你把這些都管好,你想寫明的時候才用<'name>來指明。下列兩者其實是等價,只是一個寫明Lifetime 的名字:
fn add_one<'a>(num: &'a int) -> int {
  *num + 1
}
fn add_one(num: & int) -> int {
  *num + 1
}
同時Lifetime 的範圍其實也沒那麼不好懂,大抵上就是scope,一但資源出了scope,未使用的就會被釋放掉。

結語:

Pointer, ownership, lifetime 其實是Rust 不太好搞懂的觀念,其實它就是由編譯器進行嚴格檢查,限制不當使用的C pointer,我的感想是,一但設計師適應這樣嚴格檢查,在程式設計階段自然就排除掉C/C++高自由度帶來的那些:可以但是不應該這樣寫的不安全寫法了。


參考資料:

更多內容請見
The Rust Ownership Guide
http://smallcultfollowing.com/rust-int-variations/imem-umem/guide-ownership.html
Rust by example: 17-19
http://rustbyexample.com/

2015年2月27日 星期五

人月神話

這本書其實有點老舊了,舉的例子都老到不行,不過讀起來還是覺得相當中肯。

我覺得凡是在開發軟體的開發者,管軟體開發的管理者,開軟體公司的老闆,都可以從這本書裡獲益;總括來說,開發軟體跟開發軟體系統,是完全不同的問題,前者是技術,關係的是個人工程師的熟練度;後者卻是管理,關係的是一群工程師如何溝通。

簡單的軟體大部分的軟體工程師都能寫出來,但,軟體系統需要在不同平台上測試過、需要完整的文件說明、需要讓內藏的錯誤儘可能的被找出來,這當中的工夫是以倍數在算的;如果算上每個工程師間的溝通成本,缺乏管理能讓大型團隊一事無成,這也是本書名的來由:「人月」並不是衡量軟體系統開發難度的好指標,我們都知道一個工程師寫一個月和三十個工程師寫一天,所能得到的東西是完全不一樣的。

每一章,作者都針對一個軟體系統開發的管理要訣進行說明:如何組成有效率的團隊、架構設計師的重要、團隊要如何溝通、文件怎麼管理……。可以算是作者在大型系統開發打滾多年之後總結出來的武功祕籍,一步步讀來,除了吸取作者字字珠璣的告誡,也讚嘆作者在那電腦還是珍貴資源的年代,就能完成如此大型的系統開發,網路上也有不少人整理出書中的重點,可見Heresy blog,有第一到十二章的整理(我也很好奇為啥十二章之後就沒整理了lol):
https://kheresy.wordpress.com/2011/03/22/the_mathical_man_month_p1/
https://kheresy.wordpress.com/2011/03/25/the_mathical_man_month_p2/
https://kheresy.wordpress.com/2011/04/01/the_mathical_man_month_p3/

本書的第十六章是一個頗具話題性的章節:沒有銀彈

這裡的銀彈不是指金錢,而是指在對付可怕的狼人(軟體系統專案)時,大家總希望可以出現神奇的銀彈可以讓狼人一槍斃命,但作者認為:沒有,這世界上就是沒有銀彈,沒有任何突破能讓軟體系統的生產力大幅提升一個數量級;想要弄好一個軟體系統,好好規劃、實行才是正途,就像想要對付狼人,好好改造、把它萌化才是正途

作者的論點是,因為軟體就是如此複雜的工作,現在的進步例如引入高階語言、物件導向、分時(time-sharing)、人工智慧等等,都只是處理軟體附屬上的困難,沒有直指本質的複雜核心,當附屬的困難被解決了,本質的困難仍未解決,人們在創作、溝通、理解軟體上,仍然有著無法解決的本質困難,而附屬困難並佔不到軟體開發的9/10以上。

詳細內容可見:
http://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9

我個人的看法是沒這麼悲觀,以十年來看,軟體開發也許沒有十倍進步,但長久看下來,我們的軟體生產力仍然進步神速。

現今的高階語言,也許可以用C++的standard library 為濫觴,為常用的複雜架構定下一個標準,現在要寫出複雜結構的程式碼遠比過去容易,也更不容易出錯;安全、多執行緒方面,新一代的高階語言如AZ大神推薦的Golang,最近在研究的Rust等,都針對這方面進行了補強。直譯式語言讓原型(prototype)建立更容易,展示程式概念也更加輕鬆寫意,在各種平台上也能有同樣的表現。

對測試、自動化產生code 都有更好的支援,servo用python 去剖析規格文件,自動產生出幾萬行的程式碼;網路提供的服務,例如issue tracker, git, CI測試、文件控管,林林總總的服務,程式碼的生產、測試、管控遠比過去強大得多。

十年也許太短,把「沒有銀彈」的尺度拉開,軟體本質的複雜性問題仍然被解決中,隨著軟體解決問題的能力不斷上升,我個人樂觀的覺得,我們生產軟體系統的生產力,仍然有超過一個數量級的提升。

--

引用本書開頭的一段文字,大意是這樣的:雖然程式設計師很辛苦,要不斷在軟體系統的焦油坑裡掙扎,永遠解不完的bugs,被客戶刁難,被上司責怪;但軟體還是有光明的一面,把腦中想像的東西實作出來的成就,解決問題的快意。儘管走在軟體的路上有苦有樂,總的來說,樂趣還是多於苦難。

儘管前途崎嶇,崎嶇的路上,我們還是會笑著走過去。

一本讓我頗有共鳴的書,推薦給所有正在焦油坑裡掙扎的軟體開發者們(喂)。

2015年2月25日 星期三

Rust struct, impl, trait

前言:最近被強者我同學呂行大神拉去寫Servo (https://github.com/servo/servo)
用的語言是Rust(http://www.rust-lang.org/),是個非常年輕的語言(2012年出現),另外有一個老一點的Golang(2009),基本上目前中文找不到什麼資料,就算是英文的文件本身也不太完整Orz

想說文件這種東西,只要不是亂寫愈多愈好,就在這個blog 上寫一點Rust 相關的文件,等寫多了好整理起來;基本的rust 像什麼函式怎麼宣告、if 格式之類我就不寫了,那個自己翻一翻就會了。

我出身是C/C++, Python,所以解釋角度也比較偏這樣的語言。

--

這篇介紹Rust裡的集合物件: Struct, impl 跟trait

struct在rust 裡跟C++/Python的class一樣,是物件的集合跟函式的集合,不過rust 採取的方式是用 struct A / impl A的方式,把集合的物件跟函式分開。

所以在Rust 裡很常看到這樣的寫法:
struct Car
{
   Speed: int  
}  
   
impl Car {  
  fn run(&self){  
    println!(“my speed is {:d}”, self.Speed);  
  }  
}  

一個struct 比較像C裡的struct,補上impl 就變成C++裡面的Struct/Class

同時如果我們要提供一個共同的介面(interface)呢?例如我要Car跟People都實作run 這個函式,在Rust 裡這東西可以用trait 來實作,首先先實作trait,然後就可以對struct實作trait,這東西很像java 裡面的,例如:
trait movable {  
  pub fn run(&self);  
}
  
impl movable for Car{  
  fn run(&self){  
    println!(“my speed is {:d}”, self.Speed);  
  }  
 }  
之後就可以明目張膽(?)的呼叫Car.run()了

更多內容請見:
http://rustbyexample.com/trait.html
http://tomlee.co/2013/05/traits-structs-and-impls-in-rust/

2015年2月12日 星期四

用youtube開Hangout直播

最近看到watch people coding 這個網站,也真有不少人在上面開實況寫code,覺得滿有趣的,也應該自己來開個實況試試。 目前開實況知名的有Twitch ,這方面有點難搞,目前linux 沒有這方面完整的解決方案,只能用一些程式來解決,相關網址在此: https://wiki.archlinux.org/index.php/Streaming_using_twitch.tv
不過我沒有twitch 帳號,懶得申請;帳號多開一個是一個麻煩

所幸我們有另一個解決方案:用Youtube開直播。
在youtube 右上角自己大頭貼的地方,可以進到「創作者工作室」,影片管理員內就有「現場直播」可以開,不過它要跟手機連線驗證,等於是告訴google 你的手機號碼,大家連結前請多想三分鐘;打開後它會直接用google hangout 開直播,不用特別裝其他程式。

打開後大概會長這樣:

左列有一些工具可以選,例如螢幕分享,可以指定某一個視窗做為直播的內容,例如直播寫code用的終端機或者你的webcam,目前看起來沒有混成螢幕的功能,也就是不能像其他直播一樣,畫面上還會有一個webcam 的影像;也可以開右邊的訊息視窗,不過那個跟youtube 直播頁面上的訊息沒有同步。
按開始播送後就會開始直播了。

不過我覺得直播寫code 本身就有一個問題,直播遊戲的時候,遊戲是比較簡單的東西,今天打東方是躲子彈,明天打東方也是躲子彈,看直播可能可以看一些閃躲的技術;可是寫程式不是,中途插進去的話會不知道那個人是在寫什麼,直播也很難表示出設計師在背後的架構設計,設計概念,很容易變成看一個人在打字,那樣的話直播寫程式一點意義也沒有。