為什麼我們要學/用Perl?
今天發現我這個部落格已經一個多月沒有更新了,這個實在和初衷不符,另外專案壓身,也是沒有辦法的事情,不過等這個專案做出來,或許還能寫一篇日誌留作後人用。
這篇日誌是談以Linux為開發環境下Perl的必要性,如果是在Windows下,可能Perl也就沒有這麼必要,而且在Windows下用Perl也有點違和感(不過我開始學Perl的時候倒是在Windows下給自己開發了一些工具,到現在依然常用)。所以從Windows下的開發者的角度來看,或許我這篇日誌的視角就略顯的老土了。
一、動機
我本人對Perl的感情是很真摯的,可能是僅次於vim的,碰到了很多問題(在Linux下),我第一直覺就是嘗試用Perl來解決,而實際上往往都能在200行內用一個script解決,極大地節省了我的時間。而我在學習和使用Perl的過程中,未免感受到一些雞肋,我覺得Perl的衰落是由多方面造成的:
- 身邊壓根就沒什麼人學習/使用Perl。無論是學校bbs的Linux版還是Chinaunix的Linux版和Perl版,基本都沒什麼人討論Perl技術,我當初學習Perl的時候也因此感到吃力;
- CPAN的衰落。CPAN一開始是業界一個很好的標杆,作為一個平臺,能夠很迅速地釋出自己的開源工具,讓社群變得活力四射。這是Python永遠所不能及的,但是如今,CPAN上很多包已經沒得到維護;
- 開發者的轉移。Perl上很多開發者都轉移到其他語言/指令碼語言上;
- 指令碼語言整體的衰落。從tiobe的排名上可以看出,指令碼語言在幾年前微電子發展瓶頸的時候都能達到了使用率的高峰,而隨著CPU效率限制和多核CPU的發展,並且使用者對軟體功能要求的提高,指令碼語言越來越得不到青睞,反而C這種底層語言又被大家重視起來。這幾年的排名主要受手機、平板等消費嵌入式影響,關於這一部分,我希望以後能有時間談一談;
- Perl自身發展遲緩。Perl的上下文特性也算是一大特色了。和語法受到簡化的Python不同,Perl的語法是很複雜的,解析器開發比較困難,因而版本的更新也相對遲緩。這也是Perl6遲遲不能推出的原因之一。
但是在實踐上,Perl的能力依然強大,我這篇日誌也算是我對Perl重新壯大的一中希冀吧。
二、Perl和Python
Perl和Python算是一對冤家了,跟vim和Emacs一樣,都互相鬥了很多年。但和Emacs不一樣,Python我還是用的。但作為一篇讚頌Perl的日誌,我還是免不了俗,得數落一下Python:
- 各種語法漏洞。和Perl不一樣,Python是數學家設計的,因此在語法上顯得不那麼經得起推敲:
這一簡單例子的執行結果就足以證明Python的語法上缺乏考量了:#!/usr/bin/python def foo(a=[]): a.append(1) return a print(foo()) print(foo()) print(foo([])) print(foo())
Python還有許多物件建立機制和語法分析順序引起的問題,這使得開發者要不就不使用這種特性,要不就要對這些特性死記硬背,帶來了不必要的麻煩。[email protected]:~/test$ python scope.py [1] [1, 1] [1] [1, 1, 1]
- 如動機所述,各種發行方式,比較麻煩。不過有了github和sourceforge等這些網站,也算是緩解了這個缺點的影響
- 這一點是我個人最討厭的:Python缺乏語法連貫性。這一點被Python2和Python3完美詮釋。作為一門流行的語言,有幾個特點是絕對躲不掉的:
- 長得越來越像其他流行的語言;
- 更新緩慢;
- 每次更新的同時會增添新特性,且基本維持所有原有特性,只對少數實驗性、不合理的特性作刪減。
所有的這些特點都是為了減低開發者的學習成本,並且保持已有程式碼的可維護性。但是Python3很噁心地刪除了Python2的很多已經大量被使用的特性(包括一些鉤子),並用另外一些方式來實現同樣的功能(OO的一些鉤子),還對語法進行修改(比如函式後不能沒括號了),這使得Python程式變得不那麼好長期維護了,嚴重違反了這門語言設計的初衷。
三、強大的Perl
這裡先對題目的問題作出淺層的回答:在Linux下,我們更多的會碰到和文字相關的問題,這時候我們用Perl的正則表示式可以很方便地完成各種各樣的文書處理工作,並完成報表製作,加速開發。而從語言的角度出發,Perl的語義更加統一,且程式設計的風格可以更加動態、多變。
1. 好像Perl是write-only的?
我經常聽到有人說Perl是write-only的,這個意思是Perl程式碼的可讀性巨差,寫完以後就連作者也讀不懂了,這也是一般的指令碼程式設計師極力推薦指令碼新手學習Python的原因,甚至有人已經被嚇到用shell script都不願意學習Perl了。這個觀點是大錯特錯了。
正如我上面說過,一門流行語言必然發展得越來越想其他流行的語言,Perl也不例外,從Perl的語法結構來看,它大概像下面這幾種語言(或者工具):C, shell script, awk, sed, lisp。如果一個學過shell script的程式設計師去學Perl,我相信他的第一印象就是:太像了!Perl經常被認為是shell script的延伸,很大的原因就是原始碼中無盡的$符號,而且Larry讓Perl的語句更接近C,這讓新手不會像學習shell script的時候對if語句後面的[ ]感到奇怪。
但是話又說回來,Perl確實一眼望下去並不是一門勾起人們閱讀慾望的語言,而造成這個問題的罪魁禍首我覺得就是正則表示式了。而我經常同用其他指令碼的程式設計師溝通的時候就發現,Perl基本就被等同成正則,而編寫Perl程式就是在寫正則,所以你寫你的正則,最後淹沒在bug裡去吧。一聊完我就可以下一個結論:這樣的開發者,不僅不會Perl,而且還不會正則。正則是強大的,比方說我要如何驗證郵箱的合法性?如果是正則表示式,就是一行的語句:
die "invalid email address!\n" unless $email=~m/^([a-zA-Z]\w*\.?\w*)@((?:\w+?\.)+\w+)$/;
my ($name, $domain)= ($1, $2);
好像這一行就能把人弄蒙了,但是這條語句確實可以檢查$email裡存放的字串是否email的合法格式並且在合法的時候向$name和$domain返回對應郵箱的使用者名稱和域名。但是如果不使用正則表示式呢?恐怕就得從NFA設計起了,然後再手工轉化成DFA,再用其他什麼語言來實現,只是為了完成我1分鐘就能完成的工作。
對於已經正確認識到正則匹配的重要性的開發者,用Perl來編寫正則表示式能更加迅速的完成編寫工作。Perl的正則表示式有兩個特點,一個是擴充套件性,一個是迅速。就比如說我上面的例子,\w是字符集[a-zA-Z0-9_]的同義詞,儘管如此,如果每次都要這樣來寫一個字符集的話,會很明顯降低正則表示式的可讀性和可維護性,這時候,\w作為一個內建的特殊字元來實現的功能就很明顯了。
而一個更加使得Perl正則強大的原因,就是Perl的正則支援變數展開和程式碼內插,讓正則表示式從三型文法向二型文法逼近。下面是我曾經寫過的,用Perl來檢查括號匹配的正則:
use re "eval";
#... some other code
my $ep=shift;
my $notbrkt='[^()]*';
my $brflag=0;
my (@op,@result);
while(1){
my $flag=0; #i need this flag to count matched bracket
$ep=~m/
($notbrkt) #match things before the first bracket
( #match things inside the bracket
(?:(?:
\((?{++$flag}) #increase flag to counter matched bracket
$notbrkt)+
(?:
\)(?{--$flag}) #decrease flag
(?(?{$flag}) #see if flag is cleared
$notbrkt) #if yes, then there should be something behind
)+
)*) #outer bracket and <blnkapp> finished
(.*) #eat whatever at last
/x;
my ($front,$brkt,$back)=($1,$2,$3);
#...... still something behind
學過編譯原理的人們應該知道,括號匹配是有狀態的(括號巢狀的次數),需要通過變數或者棧來記憶當前所屬的狀態。因此通常的正則匹配是沒辦法記住這個狀態的,從而使得括號匹配無法用傳統語法的正則來實現。但是這個工作在Perl裡實現也就這麼簡單。我這裡的正則實現了這樣的功能,$ep存放待匹配的字串,通過正則匹配檢查括號匹配情況,如果匹配,則把括號前、中、後三塊賦值到$front, $brkt, $back中。其中括號匹配部分的正則是遞迴形式的。(這裡提一下,傳統正則是很難編寫正確的遞迴形式的。由於傳統正則沒有條件匹配,也不能記憶狀態,這使得遞迴的終結條件很難成功,要不然就一直匹配失敗,要不然就讓不正確的匹配成功。)
這個正則匹配展示了Perl的正則表示式三個重要擴充套件:
- 變數展開。允許正則的部分規則存放在外部的變數裡,並且在執行時展開,再進行正則編譯;
- 程式碼內嵌。允許在正則匹配到某個部分的時候執行一段程式,在這裡實現了狀態的記憶;
- 條件匹配。當符合某種情況的時候才進行匹配或者不匹配。
這三個功能讓Perl的正則匹配更加強大,然而使用不當或許會降低可讀性和可維護性,但是作為黑客開發時優秀的臨時工具,這往往能極大地短縮開發時間。
但是,上面給出的擴充套件性在其他語言或者框架上也不是完全沒有被實現,就我所知.net也能玩這種玩意。但是Perl對正則匹配的處理速度估計是業界無人能匹的。對於一般的語言,如Java和Python,使用正則匹配的時候是通過OO的形式,需要執行時編譯,然後才能通過方法來匹配。但是這在Perl是可選的:每一條正則都可以在解析時編譯,或者執行時編譯,這通過識別符號/o來實現。而就算是執行時編譯的正則,Perl從VM的架構上(Perl的執行時模擬CISC機器,好像包含300+條指令?執行正則匹配的是其中幾條)對正則進行了優化,不要說其他語言,就算是grep指令也不一定及的上Perl。要比Perl更快,估計就只有手動編寫的C程式了。這也是Perl被用作大量字串工具的原因之一。
2. 函式式風格
我說Perl借鑑了Lisp不是空穴來風。我似乎已經舉不出比Perl的函式式特性更為強大的過程式語言。
函式式的美感是每個程式設計師所羨慕的。但是很多語言,如C(編譯式+硬編碼),Java(缺乏lambda運算元)等都不具有這個特性。而一些仿照函式式特性的語言也只是在原來的語言基礎上換湯不換藥,造成了一些基礎的函式式特性,卻不是真正的函式式。比如說C++的()過載允許了一定模板的函式動態生成,Python和C#具有lambda運算元,但是一個就限制多多,一個就是仿出來的。
什麼是函式式風格?要讓一門語言成為函式式的語言,最重要的門檻就是:函式是不是一等公民?而一等公民包含兩個特權:
- 函式應該允許被(執行時)傳遞
- 函式應該允許被(執行時)宣告、實現
而在這麼多種過程式語言中,只有Perl才能說是得到了很好的實現。
函式式的風格的一大特點就是遞迴,下面是我曾經寫過的一個函式,實現掃描給定資料夾下所有一般檔案(包含子目錄下的)並存放到陣列的功能:
use File::Spec;
sub filter {
my $routine=shift;
my @ret=();
map {push @ret,$_ if $routine->($_)} @_;
return @ret;
}
#...
sub scanfiles{
#...
map {push @container,File::Spec->catfile($dir,$_)}
filter(sub{
return -f File::Spec->catfile($dir,$_[0]);
},readdir $dh);
#...
}
其中filter函式和python的filter函式實現同樣的功能(對,Perl裡沒有filter函式,也沒有sum函式,不能再鬱悶...),scanfiles函式實現我上面所述的功能,我已經把程式碼裁剪至只有函式式的部分(這四行應該被當成只有一行)。這一部分實現的功能是把$dh描述的資料夾下的所有通常檔案通過catfile處理後壓入@container中。從這一句函式式的風格可以看出,函式式的程式碼更能保證自然人的思路順序,並且讓程式碼更加緊湊。可以看見,這裡我建立了一個匿名函式,判斷輸進去的檔案是否通常檔案,並且我可以保證這個函式必然是執行時生成的。為什麼這麼說?注意到catfile函式的作用是把輸入的陣列按照當前OS的環境串成檔案路徑的格式,而我這串呼叫存在於一個foreach迭代塊中,$dir是隨著掃描目錄一直在變的,如果是解析時生成,我的結果不可能是正確的。
這裡表明了Perl的函式(正規術語是子例程)是執行時生成的!
所以我完全可以寫出下面的程式碼在主程式碼塊,並且完全可以保證實際執行的正確性:
my @functions=();
map {push @functions,
sub{ return $_ }
} (1..$n);
#here $n is determined by any other logic and functions!!!!
如果你看到這裡,我相信你已經完全瞭解了函式式的特點,在這裡我動態地生成了一系列的函式,這些函式返回1到$n,並且這裡的上限$n根本不由也無須我這個程式碼塊所決定。這裡生成的程式碼塊實現了當時LISP首次提出的流的概念。
當然,在懶人眼裡看到這個程式碼相信是另外一個想法:寫C++的時候定義一個類的時候總要對private的資料成員手動編寫get和set函式,多累啊!在Perl,你有福了:
my @attrs=qw(attr1 attr2 attr3); #a lot and a lot
foreach (@attrs) {
eval("sub $_ {
my ($self, $val)[email protected]_;
$self->{$_}=$val if defined $val;
$self->{$_}
}");
}
這裡的OO通過雜湊來實現。這個程式碼塊執行在OO風格的Perl的模組中,大意是一個懶人程式設計師通過foreach迴圈通過eval函式執行時生成了一批成員的get set函式(注意到Perl的get set函式是一體的,通過過載實現(ps. 儘管Perl的概念裡不存在傳統意義的過載(pps. 這一段括號巢狀可以用前面的括號匹配正則來檢驗哦)))。
在Perl裡,函式式是說不完的話題,我一開始先學習了Perl再學習了Scheme(一種Lisp的方言),發現所有的程式碼都可以用Perl來實現和解釋。最後,以用Perl實現的函式式風格的OO來結束這一節:
package OOinPerl;
sub new{
my $self=shift;
my $type=ref $self || $self;
#... somehow fetch the parameters from @_ and save in $a, $b and $c.
my $data={a=>$a,b=>$b,c=>$c}; #this is a hash table reference
my $this=sub{
my $field=shift;
$data->{$field}=shift if @_;
$data->{$field}
};
bless $this, $type
}
#... other functions
在這裡,例項的本質是一個子例程,不要太神奇!
(關於函式式風格的OO,通過Scheme也可以實現,感興趣的人可以找我要程式碼,希望我們能夠交流一下。)
3. 開發迅速
把這個當優點可能有點牽強(倒不如說是上手迅速),這更多是從我自身出發來說的。
我大概是一年多兩年前才開始接觸Perl,剛開始學習缺乏交流學習起來比較困難,後來慢慢地習慣了,通過看大小駱駝和黑豹書來學習,迅速熟悉過來,到現在已經是我解決小問題的主要語言(之一)。當處理起和文字相關的小問題的時候,Perl的程式碼量可以少得驚奇,往往都是 fetch=>filter=>handle三部曲就可以解決。在日常生活中,Perl往往就是編寫一發寫好解決問題再也不維護的小程式的語言。和一些標準模組結合,可以實現一些很實用的功能(比如說檢索極影自上次檢查時間為止,更新了哪些在追的動畫,字幕組匹配)。而Perl對於這些任務,包括資料庫的讀取和回寫,往往只需要200行不到的程式碼,對同等規模的程式碼,諸如Python等其他語言可能並不能完成同歸模的問題。
而對於有shell程式設計,sed、awk程式設計經驗的人,掌握和使用Perl或許會更快。把所有的Linux指令碼都用Perl來實現,說不準也是個相當有趣的做法。
4. 程式碼相當接近自然語言
在這麼多語言裡面,也就數Perl是能用來編詩歌的。Perl的社群CPAN裡面曾經有過Perl詩歌大賽,就是用Perl來編寫詩歌。這樣編寫的詩差不多能夠執行(可能要先定義一下額外的函式)。這得益於Perl自由的程式設計風格和各種語法糖使得Perl的程式碼可以很接近自然語言。通過讀大駱駝可以知道很多讓Perl程式碼更接近自然語言的方法。
5. 就因為酷 !
扯了不少廢話,其實我說Perl的特點一個字就可以概括,那就是:酷!
Perl太酷了。對於每個開發者,針對同一個問題可能會有完全不同思路的解決方案,這一特性開拓了開發者的思路,應當受到開源開發者的追捧。想想一下,如果你有一個任務,目標是完成就可以了,並且涉及了大量的文書處理和網路相關的技術。你的同伴苦苦思索一步步解決網路,然後死在了大量而多變文書處理階段,而你只要100+行就把問題完美解決了。當你把程式碼給你同伴看的時候,我覺得他心裡的“what the fuck”感和你心裡的痛快感可以形成鮮明的對比。
Perl還有很多奇形怪狀的特性支援著酷這個特點,什麼上下文阿,字串-數字平滑轉換阿,語言定製阿都在其中。另外值得一提的是,Perl6的特性比Perl5更加酷,可以自由地定製自己的Perl,有更加動態的特性,只可惜因為解析器難以實現已經難產了十多年。不過最近有風聲好像是快釋出了(天曉得是真是假)。
三、Perl好像還真有這麼些不好
好吧,其實Perl現在在tiobe的排名上已經日益下降了,這不僅應該說時事上的因素和其他語言新增添的優勢(Perl的語法和功能增添相對沒這麼頻繁),Perl自身也有讓人感到雞肋的地方:
- 太酷了,酷到別人的程式碼基本看不懂。兩個思路不一樣的人又怎麼可能在一起呢?想都想不到一塊去,估計要光靠讀程式碼讀出個所以然是一件不容易的事情;
- 不好模組化。Perl和Python的模組化方式其實蠻像的。但是Perl在模組化程式設計的風格比較怪異,光靠讀程式碼不讀書很可能不能理解箇中含義,因此有引出下一個缺陷;
- 可讀性太差。這裡的可讀性差一在於變數的形式和正則表示式,二在於程式碼組織缺乏約束。Perl可以隨處定義函式,也可以用各種方法生成函式。要是沒有心理準備和先前知識,想去了解一段隨手寫的程式碼的行為,恐怕是一件不容易的事;
- 細節繁多。細節可以增加語言的威力,但同時也要求編寫者對這門語言的各種細節瞭如指掌才能加以利用。比如說一開始給出Python的例子,如果不瞭解Python創造陣列的時機,那麼程式碼的行為和預想的不一樣的原因也無從追起。同樣,在Perl中,上下文機制,list和array這些概念讓開始學習的我疑惑過一段日子,不過這些問題在Larry的大駱駝都能夠能到語言學上的解釋。
四、後話
Perl是門很有趣的語言。真正投入學習過Perl的人估計都不會反對我。如果我提出的Perl的一些很爽很過癮的地方吸引到了你,我真心奉勸一句:不妨學一學,Perl能開啟一個全新的視角對待程式。
相關推薦
為什麼我們要學/用Perl?
今天發現我這個部落格已經一個多月沒有更新了,這個實在和初衷不符,另外專案壓身,也是沒有辦法的事情,不過等這個專案做出來,或許還能寫一篇日誌留作後人用。 這篇日誌是談以Linux為開發環境下Perl的必要性,如果是在Windows下,可能Pe
Django : 網路應用開發為什麼我們要學Django?
如果你是Python的粉絲,又對網站與網路應用開發感興趣,那麼學習Django就不是為什麼要學的問題,而是要怎麼學好的問題了。小編我從事網站開發多年,之前主要是利用PHP+MySQL的黃金組合來進行,最近才改用基於Python的網站開發框架Django來開發網站與網路應用。在
別再關心AI怎麽好了,我們要搞懂AI怎麽用
ant 坐標 rgb weight 部分 基本 安利 世界 ali 在今天的中國,想要了解AI,最怕的是什麽?答案也許只有一個,那就是開會。如今的人工智能大會基本是有套路的:首先要提問AI到底會不會取代人類;然後各個專家發言,暢想一下AI的美好未來;最後炫一張復雜的PPT或
為什麼我們要用jdk1.8
可能很多公司現在用的還是jdk1.6,因為種種原因一直沒有升級以及spring框架對應的也是spring3.2.8左右 1.6和1.8之前的區別難道僅僅是增加了幾個新特性?如jdk1.8的Lambada表示式特性? 其實很多我們看不到的地方也做了效能優化,個人覺得優化的最重
C語言都能用來幹嗎、我為什麼要學C語言
最近在學C語言,可是越學習就越覺得迷茫,不知道我能用它來幹什麼? 現在總結一下很多網友的回答,給大家一些參考! 一 、 c語言是計算機技術的基礎,是資訊科技的基礎,是自動化技術的基礎,是很多電子裝置能夠執行的基礎,學了C語言,你可以開發: 1.
大資料爆發,我們要不要學?適不適合學?
最近兩年,大資料這個詞非常火,以大資料為基礎和核心的人工智慧也以迅雷不掩耳之勢蔓延到各個領域,無人駕駛,無人超市,智慧城市等等。毫無疑問,火爆的大資料已然成為當今網際網路世界中的新寵兒,創造著巨大的商業價值,是當今網際網路巨頭的必爭之地。 推薦下小編的大資料學習群;251956502,不管你是小
為什麼我們要儘可能使用Iterator介面中的remove方法而不是用Collection介面中的remove方法
最近在看《資料結構與演算法分析》(Java語言描述)一書,看到第3.3.2 這一節時介紹Iterator介面。書中說道,“Iterator介面中包含一個方法,叫做remove()。該方法可以刪除next最新返回的項。雖然Collection介面也包含一個remo
為什麼我們要用Spring?
在之前的文章說說java反射(2)反射的價值我們對java反射的內容有了一定的瞭解,並且通過反射機制做了一個簡單的框架,也算是對於Spring框架的鋪墊.接下來了解一下我們使用Spring框架的意
為什麼我們要用分散式檔案系統(經歷後的感觸)
1、為什麼分散式檔案系統要採用特定的組織結構來儲存檔案? 直接按照檔案的原始路徑進行儲存和複製,這樣就可以直接通過應用服務進行靜態化訪問,從而大幅度提升效能。怎麼樣,這個主意不錯吧? 等等,我們好像又繞回去了….. 這樣的一個系統,大概是一個共享檔案系統?或者是一個檔案分
用四個點,告訴你為什麼要學Python
1.2018年程式語言火熱度排行 時代變遷如此之快,誰又能想到當我們還在羨慕大雄的機器貓時現在人工智慧已經開始步入我們的生活點滴呢?我先給大家小小的科普一下:二十世紀四十年代當計算機剛剛問世的時候,程式設計師必須手動控制計算機,當時的計算機也是非常昂貴的。不久後,計算
Java內存使用量測試 看看我們天天在用的JVM到底浪費了多少內存資源
數據 static ini apm long setlength into set等 dom JVM內存使用量測試測試各種不同的數據結構在JVM中的內存使用量 1 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
程序員難學麽 要學多久才是中級java
學習 連續 php 時間 角色 做的 並且 課程 c++ 程序員是一個需要終生學習的職業。我非常贊成終生學習,你應該這樣做。但是,在軟件開發領域,有如此多的新技術,有如此多要學習的東西,我們在學習中會感覺被完全壓垮了。 你感覺你一直在扮演追趕的角色,但是一直都趕不上。就像是
6-感覺身體被掏空,但還是要學Pandas(上)
搜索結果 分配 淘寶 時間 amr 一次 記得 每天 包含 關註群主朋友圈的人都知道,本周群主過得RIO充實,每天工作到半夜寫爬蟲,先後寫了Linkedin,生E經、生意參謀以及淘寶關鍵詞搜索結果等爬蟲。記得去年寫工商信息爬蟲時是灰頭土臉的,雖然每爬一次隨機sleep幾秒,
7-感覺身體被掏空,但還是要學Pandas(下)
裏的 toe 時間序列 enc 分組 文件 mod 期待 都是 本周群主用了兩天時間為浙師大的《旅遊大數據分析師——Pandas數據清洗》課程備課,和Pandas來了一次深度親密接觸。現在做夢都是DataFrame變形:stack,unstack,pivot table
為什麽我們要閱讀源碼?
before 模仿 畢業 開拓 廣告 思考 工程 github 語文 https://zhuanlan.zhihu.com/p/26181360 ***************************** 程序員每天都和代碼打交道。經過數年的基礎教育和職業培訓,大部分程序
為什麽要學互聯網技術
php java python 互聯網經濟的到來,讓人們生活發生了明顯的改變,網購、手機APP、微信等已經成為當下生活模式的代言。超市、百貨的付款方式,開始從現金到刷卡,再到支付寶、微信;各大實體商鋪、酒店開始使用會員卡管理系統提升對用戶的管理和品牌擴散;旅遊業、銀行等開始以微信來做推廣和服務用戶
最近好煩啊要學各種東東
dalvik dal baidu http lis aid com hao123 ongl DaLVIk%E5%86%85%E5%AD%98%E8%B0%83%E6%95%B4%E5%8F%8A%E7%9B%91%E6%8E%A7%E6%8A%A5%E5%91%8A ht
為什麽程序員一定要會用Google和Stack Overflow?
google jquery 如果 dom 才會 www. 想要 pac 時間 作為程序員,用Google比用百度更節省時間,此話不假。 在法國工作也有4年了,加上之前的兩個6個月的實習,勉強算“5年”工作經歷吧… 雖說我離編程大牛還相距甚遠,但是: 這些年編程的一個很深的
為什麽要學攝影 ?
層層疊疊 仙境 全部 一個 安靜 存儲 攝影 真的是 apple 以前,我有個壞習慣。無論第一天照片拍的多好,第二天總會手癢著想刪掉。以至於做攝影師這麽多年,我竟然沒有自己完整的作品集。年初的時候,決定徹底改掉這個壞習慣。幾個月下來,有了挺豐富的作品。如今回頭看看,每一張照
PHP7中我們應該學習會用的新特性
默認 很多 處理 strong 支持 體驗 int 補充 urn PHP7於2015年11月正式發布,本次更新可謂是PHP的重要裏程碑,它將帶來顯著的性能改進和新特性,並對之前版本的一些特性進行改進。本文小編將和大家一起來了解探討PHP7中的新特性。 1. 標量類型聲明 我