在2020年5月17日退个,HengLi在它的一篇博客「Fast high-level programming languages」提到赠法,他一直在尋找一門編程語言勋功,生物學(xué)家容易使用而且速度還快递鹉。( I have always been searching for a high-level language that is fast and easy to use by biologists. )
于是在這篇博客中弓候,他評估了一些高級編程語言的處理速度郎哭,包括,C, Python, Javascript, LuaJIT, Nim, Crystal菇存,Rust夸研。其中Rust在FASTQ的解析速度上略勝于C語言。
同時在2020年12月的nature的technology feature中也有一篇是關(guān)于Rust依鸥,「Why scientists are turning to Rust」地址為https://www.nature.com/articles/d41586-020-03382-2
里面有一張圖亥至,是評估Rust近年來的社區(qū)狀態(tài)的(即相關(guān)包的增長數(shù)量),從中可以發(fā)現(xiàn)Rust的增長超過了R。
我并不是某個編程語言的信徒姐扮,平常用的最多的是R和Python絮供,同時經(jīng)常性的找機會學(xué)習(xí)C和C++,以及每隔幾個月會去嘗試學(xué)一門新的編程語言茶敏。
這一次壤靶,我是跟著極客時間里的一門課,「陳天·Rust編程第一課」學(xué)習(xí)Rust惊搏。
基礎(chǔ)配置:安裝Rust工具鏈
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
我使用VScode進行開發(fā)贮乳,并安裝了如下插件
- rust-analyzer (語法分析)
- rust syntax (語法高亮)
- crates
- better toml (TOML格式更好的展示)
- rust test lens
- Tabnine (基于機器學(xué)習(xí)的自動補全,不只是Rust)
接著恬惯,嘗試使用Rust構(gòu)建第一個程序向拆。我的目標(biāo)是讀取Fasta,統(tǒng)計其中的A, T, C, G各有多少個酪耳。
完成這個需求浓恳,有兩個思路亭引,第一個是調(diào)用成熟的庫剖踊,第二個是自己造輪子寫一個函數(shù)。
對于思路1揪罕,我使用關(guān)鍵詞讹堤,Rust和Bio搜索到一個庫叫做吆鹤,rust-bio。https://rust-bio.github.io/
接下來洲守,使用cargo new創(chuàng)建項目
cargo new fasta_count
第二步: 添加依賴疑务。編輯 Cargo.toml , 添加依賴信息
[dependencies]
bio = "0.37.1"
第三步: 學(xué)習(xí)rust-bio文檔,查找相關(guān)函數(shù)梗醇,然后在 src/main.rs中編寫代碼知允。
use bio::io::fasta;
use std::io;
fn main() {
let reader = fasta::Reader::new(io::stdin());
let mut nb_a = 0;
let mut nb_t = 0;
let mut nb_c = 0;
let mut nb_g = 0;
for result in reader.records(){
let record = result.expect("Error during fasta record parsing");
for &base in record.seq() { //return sequence
if base == b'a' || base == b'A' {
nb_a += 1;
} else if base == b'c' || base == b'C'{
nb_c += 1;
} else if base == b'g' || base == b'G'{
nb_g += 1;
} else if base == b't' || base == b'T'{
nb_t += 1;
}
}
}
println!("A:{}, C:{}, G:{}, T:{}", nb_a, nb_c, nb_g, nb_t);
}
我使用標(biāo)準(zhǔn)庫io::stdin從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù),然后利用fasta::Reader的new出一個新的reader實例叙谨。對該實例的records對象進行遍歷温鸽,得到fasta的中記錄,record手负。最后對記錄中序列進行遍歷涤垫,得到不同堿基的數(shù)目。
第四步:編譯代碼竟终。cargo會先將依賴環(huán)境下載到當(dāng)前項目下蝠猬,然后在進行編譯。
cargo build
編譯結(jié)果存放在 target的debug目錄下统捶,名為fasta_count榆芦。我們運行程序柄粹,得到結(jié)果。
cat TAIR10.fa | target/debug/fasta_count
# A:38223602, C:21551439, G:21528650, T:38177852
第一種思路的代碼匆绣,是看教程里使用案例"使用HTTP獲取HTML然后保存成Markdown"后驻右,自己嘗試的第一個和生信相關(guān)程序。在嘗試過程中犬绒,由于對基本的數(shù)據(jù)類型不了解旺入,所以在處理字符的時候,還專門去檢索了下 'a' 和 b'a'的區(qū)別凯力,以及為什么要用一個b''.
鑒于自己的水平太次茵瘾,還是決定后續(xù)學(xué)習(xí)更多Rust基礎(chǔ)再來嘗試吧。
最后說說自己的編程體驗:
每一門編程語言都有其特殊的語法咐鹤,在Rust中拗秘,Rust用let對類型進行推導(dǎo),而C++中是用auto進行類型推導(dǎo)祈惶。Rust和Python類似雕旨,可以直接用for x in xxx
對xxx進行遍歷,而C++則是 for (auto x : xxx )
捧请。Rust使用{}聲明代碼塊凡涩,而不是Python那樣子使用縮進。在函數(shù)返回上疹蛉,Rust可以用return 顯示說明要返回的內(nèi)容活箕,還是隱式將最后一個值(不能加上;)作為返回值,這個跟R語言又很像可款。當(dāng)然還有函數(shù)定義育韩,python用def 函數(shù)名, C和C++是返回值 函數(shù)名,R用 函數(shù)名 <-function, GO是 func 函數(shù)名, Rust用的是新的縮寫 fn 函數(shù)名闺鲸。
每次我學(xué)一門編程語言的時候筋讨,我都在想,這種語法上的特立獨行摸恍,到底是為了什么呢悉罕?
吐槽完語言,最后夸夸Rust的編譯器立镶。它的編譯器非常強大壁袄,能夠很好的指出的我代碼中的錯誤,便于檢索debug谜慌。甚至有些時候都不需要檢索然想,因為它會直接跟你說怎么改莺奔。就仿佛有一個老師在你方便欣范,跟你說变泄,你這里不對,你要這樣子做恼琼。