Perl 6 documenthtml
翻譯前端
本翻譯意在幫助理解原文,因我的水平有限,不免會有翻譯不當,若是疑惑請在評論中指出。node
原文git
簡而言之,之前作什麼如今怎麼作 吾欲以 Perl 6行 Perl 5之所爲,當何如?
這個頁面嘗試去索引從 Perl 5到 Perl 6的語法以及語義上的變化。那些在 Perl 5中正常工做的,在 Perl 6中卻要換一種寫法的語法應該被列出在這裏(而許多 Perl 6的新特性以及風格就不會)。
所以,這個頁面並非針對 Perl 6初學者的手冊或者進階文章,它是爲有着 Perl 5知識背景的 Perl 6學習者以及移植 Perl 5 代碼到 Perl 6的人員準備的技術文檔(雖然Automated Translation可能會更方便一些)。
注意當文檔中咱們說「如今」時,更多的意思是「你如今正在學習的 Perl 6」,並無暗示說 Perl 5忽然過期了,偏偏相反,大多數的咱們都深愛 Perl 5,咱們但願 Perl 5能再繼續使用好多年,事實上,咱們的重要目標之一就是讓 Perl 5和 Perl 6之間順利交互。不過,咱們也喜歡 Perl 6的設計目標,相比 Perl 5中的設計目標,更新穎,更好。因此,咱們中的大多數人都但願在下一個十年或者兩個十年,Perl 6能成爲更流行的語言,若是你想把「如今」看成將來,那也是很好的,但咱們對致使爭論的非此即彼的思想不感興趣。程序員
參見Perl 6模塊列表
若是你使用的模塊尚未被移植到 Perl 6,並且在列表中沒有替代品,可能在 Perl 6中的使用問題尚未解決。
有不少目標是爲了在 Perl 6中use
Perl 5模塊的工程:
v5模塊意在讓Rakudo自身解析 Perl 5的代碼,而後編譯成和 Perl 6一樣的字節碼。
Inline::Perl5模塊使用一個內嵌的perl
解釋器運行 Perl 6腳本中調用到的Perl 5代碼。
其中,Inline::Perl5更完善,更有前途。github
若是你有讀過 Perl 6的代碼,一個最明顯的地方就是方法調用語法如今使用點替代了箭頭:web
$person->name; # Perl 5 $person.name; # Perl 6
點符號即容易書寫又更加符合行業標準,不過咱們也想賦予箭頭別的使命(字符串鏈接如今使用~
運算符)。
對於直到運行時期才知道名字的方法調用:正則表達式
$object->$methodname(@args); # Perl 5 $object."$methodname"(@args); # Perl 6
若是你省略了雙引號,那麼 Perl 6會認爲$methodname
包含一個Method
對象,而不是簡單的方法名字字符串。shell
Perl 5在容許空白的使用上有着驚人的靈活性,即便是在嚴格模式(strict mode)而且打開警告(warnings)環境下:編程
# 不符合習慣,可是在 Perl 5是能夠的 say "Hello".ucfirst ($people [$ i] -> name)."!"if$greeted[$i]<i;
Perl 6也支持程序員書寫自由和代碼的創造性,可是權衡語法靈活性和其一致性、肯定性、可擴展的grammar,支持一次解析以及有用的錯誤信息,集成如自定義運算符的特性,而且不會致使程序員誤用的設計目標,而且,「code golf」的作法也很重要,Perl 6的設計在概念上更簡潔而不是擊鍵上。
所以,在 Perl 5的語法的許多地方空白都是可選的,但在 Perl 6裏多是強制的或者禁止的,這些限制中的許多不太可能關係到現實生活中的 Perl 代碼(舉例來講,sigil 和變量名字之間的空格被禁止了),可是有一些可能不太幸運的和一些 Perl hacker的編程習慣風格相沖突:
參數列表的開括號以前不容許包含空白
substr ($s, 4, 1); # Perl 5 (這在 Perl 6 意味着傳遞了一個列表參數) substr($s, 4, 1); # Perl 6 substr $s, 4, 1; # Perl 6 替代括號的風格
關鍵字後面要緊跟空白
my($alpha, $beta); # Perl 5,這在 Perl 6裏面將嘗試調用例程my() my ($alpha, $beta); # Perl 6 if($a < 0) { ... } # Perl 5,在 Perl 6將會停止執行 if ($a < 0) { ... } # Perl 6 if $a < 0 { ... } # Perl 6,更符合習慣 while($x-- > 5) { ... } # Perl 5,在 Perl 6將會停止執行 while ($x-- > 5) { ... } # Perl 6 while $x-- > 5 { ... } # Perl 6,更符合習慣
前綴運算符後面或者後綴運算符、後綴環繞運算符(包含數組、哈希下標運算符)的前面不容許包含空白。
$seen {$_} ++; # Perl 5 %seen{$_}++; # Perl 6
方法調用運算符周圍不容許出現空白:
$customer -> name; # Perl 5 $customer.name; # Perl 6
中綴運算符在可能和存在的後綴運算符或者後綴環繞運算符衝突時前面要包含空白:
$n<1; # Perl 5 (在 Perl 6裏面可能和後綴環繞運算符 < > 衝突) $n < 1; # Perl 6
然而,你可使用unspace在 Perl 6的不容許使用空白的代碼那增長空白:
# Perl 5 my @books = $xml->parse_file($file) # 一些註釋 ->findnodes("/library/book"); # Perl 6 my @books = $xml.parse-file($file)\ # 一些註釋 .findnodes("/library/book");
參見 Perl 6設計文檔中的S03#Minimal whitespace DWIMmery和S04#Statement parsing。
在 Perl 5中,數組和哈希使用的 sigil 取決於怎樣訪問它們,在 Perl 6裏面,不論變量怎樣被使用,sigil 是不變的 - 你能夠把他們做爲變量名字的一部分(參見 Dereferencing)。
sigil $
如今老是和「標量」變量一塊兒使用(好比$name
),再也不用於數組索引以及哈希索引。這就是說,你仍然可使用$x[1]
和$x{"foo"}
,可是它們是做用在$x
上,並不會對類似名字的@x
和%x
有影響,它們如今能夠經過@x[1]
和%x{"foo"}
來訪問。
sigil @
如今老是和「數組」變量一塊兒使用(好比@month
,@month[2]
,@month[2, 4]
),再也不用於哈希值切片。
sigil %
如今老是和「哈希」變量一塊兒使用(好比%calories
,%calories<apple>
,%calories<pear plum>
),再也不用於數組鍵值切片。
sigil &
如今始終(而且再也不須要反斜槓了)引用一個命名子例程/運算符的函數對象並不會執行它們,換句話說,把函數名字看成「名詞」而不是「動詞」:
my $sub = \&foo; # Perl 5 my $sub = &foo; # Perl 6 callback => sub { say @_ }; # Perl 5 - 不能直接傳遞內建過程 callback => &say; # Perl 6 - & 給出任何過程的「名詞」形式
由於 Perl 6一旦完成編譯就不容許在做用域內添加/刪除符號,因此 Perl 6並無與 Perl 5中undef &foo;
等效的語句,而且最接近 Perl 5的defined &foo;
是defined &::("foo")
(這使用了「動態符號查找(dynamic symbol lookup)」語法)。然而,你可使用my &foo;
聲明一個可修更名字的子例程,而後在運行過程當中向&foo
賦值改變它。
在 Perl 5中,sigil &
還能夠用來以特定的方式調用子例程,這和普通的過程調用有些許不一樣,在 Perl 6中這些特殊的格式再也不可用:
&foo(...),使函數原型失效
在 Perl 6中再也不有原型了,對你來講,這和傳遞一個代碼塊或者一個持有代碼對象的變量做爲參數沒有什麼不一樣:
# Perl 5 first_index {$_ > 5} @values; &first_index($coderef, @values); # 禁止原型而且傳遞一個代碼塊做爲第一個參數 # Perl 6 first {$_ > 5}, @values, :k; # :k 副詞使第一個參數返回下標 first $coderef, @values, :k;
&foo,還有 goto &foo; 用來重用調用者的參數列表或者替換調用棧的調用者
sub foo { say "before"; &bar; say "after" } # Perl 5 sub foo { say "before"; bar(|@_) say "after" } # Perl 6 - 須要顯式傳遞 # 建議使用Rakudo中的 .callsame sub foo { say "before"; goto &bar } # Perl 5 # 建議使用Rakudo中的 .nextsame 或者 .nextwith
在 Perl 5中,sigil *
指向一個 GLOB 結構,繼而 Perl 可使用它存儲非詞法變量,文件句柄,過程,還有格式(?formats)(不要和 Perl 5的用來讀取目錄中的文件名的內建函數 glob()
混淆了)。
你最可能在不支持詞法文件句柄,但須要傳遞文件句柄到過程時的早期 Perl 版本代碼中與 GLOB 邂逅:
# Perl 5 - 古法 sub read_2 { local (*H) = @_; return scalar(<H>), scalar(<H>); } open FILE, '<', $path or die; my ($line1, $line2) = read_2(*FILE);
在翻譯到適合 Perl 6的代碼前,你可能須要重構你的 Perl 5代碼以移除對 GLOB的依賴:
# Perl 5 - 詞法文件句柄的現代用法 sub read_2 { my ($fh) = @_; return scalar(<$fh>), scalar(<$fh>); } open my $in_file, '<', $path or die; my ($line1, $line2) = read_2($in_file);
而後這是可能的一個 Perl 6翻譯代碼:
# Perl 6 sub read-n($fh, $n) { return $fh.get xx $n; } my $in-file = open $path or die; my ($line1, $line2) = read-n($in-file, 2);
如今,數組的索引和切片再也不改變變量的sigil,而且在還可使用副詞控制切片的類型:
索引
say $months[2]; # Perl 5 say @months[2]; # Perl 6 - @ 替代 $
值切片
say join ',', @months[6, 8..11]; # Perl 5, Perl 6
鍵值切片
say join ',', %months[6, 8..11]; # Perl 5 say join ',', @months[6, 8..11]:kv; # Perl 6 - @ 替代 %,而且使用 :kv 副詞
如今,哈希的索引和切片再也不改變變量的sigil,而且在還可使用副詞控制切片的類型。還有,花括號中的單詞下標再也不自動引用(即自動在兩邊加上雙引號),做爲替代,老是自動引用其內容的新的尖括號版本是可用的(使用和qw//
引用構造相同的規則):
索引
say $calories{"apple"}; # Perl 5 say %calories{"apple"}; # Perl 6 - % 替代 $ say $calories{apple}; # Perl 5 say %calories<apple>; # Perl 6 - 尖括號,% 替代 $ say %calories«$key»; # Perl 6 - 雙尖括號內插做爲一個 Str 列表
值切片
say join ',', @calories{'pear', 'plum'}; # Perl 5 say join ',', %calories{'pear', 'plum'}; # Perl 6 - % 替代 @ say join ',', %calories<pear plum>; # Perl 6 - (更漂亮的版本) my $key = 'pear plum'; say join ',', %calories«$key»; # Perl 6 - 在內插以後完成切分
鍵值切片
say join ',', %calories{'pear', 'plum'}; # Perl 5 say join ',', %calories{'pear', 'plum'}:kv; # Perl 6 - 使用 :kv 副詞 say join ',', %calories<pear plum>:kv; # Perl 6 - (更漂亮的版本)
還有注意下標花括號如今再也不是一個特殊的語法形式,而是一個普通的後綴環繞運算符,所以檢測鍵是否存在和鍵移除使用副詞完成。
在 Perl 5中,引用一個匿名數組和哈希以及過程的在它們建立的時候返回,引用一個存在的命名變量和過程使用\
運算符完成。
在 Perl 6中,匿名數組和哈希以及過程依然在它們建立的時候返回,引用一個命名的過程需在它們的名字前面加一個 sigil &
,引用一個存在的命名變量使用item
上下文:
my $aref = [1, 2, 9]; # 同時適用於 Perl 5&6 my $href = {A => 98, Q => 99 }; # 同時適用於 Perl 5&6 my $aref = \@aaa; # Perl 5 my $aref = item(@aaa); # Perl 6 my $href = \%hhh; # Perl 5 my $href = item(%hhh); # Perl 6 my $sref = \&foo; # Perl 5 my $sref = &foo; # Perl 6
在 Perl 5中,對一整個引用解引用的語法是使用 類型-sigil 和花括號,引用放在花括號裏面,在 Perl 6中,由花括號變爲了圓括號:
# Perl 5 say ${$scalar_ref}; say @{$array_ref}; say keys %{$hash_ref}; say &{$sub_ref}; # Perl 6 say $($scalar_ref); say @($array_ref); say %($hash_ref); say &($sub_ref);
注意在 Perl 5和 Perl 6中,圍繞的花括號或者括弧都常常被省略,雖然省略下降了易讀性。
在 Perl 5中,箭頭運算符->
,用來單次訪問複合引用或者經過引用調用一個過程,在 Perl 6中,咱們使用點運算符.
完成這一任務:
# Perl 5 say $array_ref->[7]; say $hash_ref->{'fire bad'}; say $sub_ref->($foo, $bar); # Perl 6 say $array_ref.[7]; say $hash_ref.{'fire bad'}; say $sub_ref.($foo, $bar);
在最近的 Perl 5版本(5.20或者之後),一個新的特性容許使用箭頭運算符解引用,參見實驗性的後綴解引用,這個新特性和 Perl 6中的.list
以及.hash
方法對應:
# Perl 5.20 use experimental qw < postref >; my @a = $array_ref->@*; my %h = $hash_ref->%*; my @slice = $array_ref->@[3..7]; # Perl 6 my @a = $array_ref.list; # 或者 @($array_ref) my %h = $hash_ref.hash; # 或者 %($hash_ref) my @slice = $array_ref[3..7];
「Zen」切片能夠有一樣的效果:
# Perl 6 my @a = $array_ref[]; my %h = $hash_ref{};
參見 S32/Containers。
更多運算符細節請參見S03-operators。
未改變的:
, 列表運算符
\+ 數值加法
\- 數值減法
* 數值乘法
/ 數值除法
% 數值求餘
** 數值求冪
++ 數值自增
-- 數值自減
! && || ^ 邏輯運算符,高優先級
not and or xor 邏輯運算符,低優先級
== != < > <= >= 數值比較
eq ne lt gt le ge 字符串比較
在 Perl 5,這些運算符返回 -1,0 或者 1,而在 Perl 6,它們返回值對應的是 Order::Less
, Order::Same
和 Order::More
。cmp
如今叫作 leg
(字符串比較),它只適用於字符串上下問比較。<=>
仍然只適用於數值上下文。cmp
在 Perl 6中同時具有<=>
和leg
的功能,這依賴於參數的類型。
運算符自己沒有改變,實際匹配的內容規則依賴於參數的類型,不過 Perl 6中的這些規則跟 Perl 5有很大不一樣。參見S03/Smart matching。
在 Perl 5中,$
|
^
的行爲依賴於參數的內容,好比,31 | 33
的返回值和"31" | "33"
是不一樣的。
在 Perl 6中,這些單字符運算符都被移除了,替代它們的是能夠強制把參數轉換到須要的內容的雙字符運算符。
# 中綴運算符 (兩個參數,左右各一個) +& +| +^ 按位和 按位或 按位異或 :數值 ~& ~| ~^ 按位和 按位或 按位異或 :字符串 ?& ?| ?^ 按位和 按位或 按位異或 :邏輯 # 前綴運算符 (一個參數,在運算符後) +! 非:數值 ~! 非:字符串 ?! 非:邏輯 (做用和 ! 運算符同樣)
被+<
和+>
取代。
say 42 << 3; # Perl 5 say 42 +< 3; # Perl 6
在 Perl 5裏面,=>
的行爲就想一個逗號,可是會自動引用(即加上雙引號)左邊的參數。
在 Perl 6裏面,=>
是 Pair 運算符,這是最主要的不一樣,可是在許多狀況下行爲都和 Perl 5裏面相同。
在哈希初始化時,或者向一個指望哈希引用的方法傳遞一個參數時,=>
的用法就是相同的:
# 同時適用於 Perl 5&6 my %hash = (AAA => 1, BBB => 2); get_the_loot('diamonds', {quiet_level => 'very', quantity => 9}); # 注意花括號
在爲了避免再引用(兩邊加上雙引號)列表的一部分而使用=>
做爲一種便利的方式時,或者向一個指望鍵,值,鍵,值這樣的平坦列表的方法傳遞參數時,繼續使用=>
可能會破壞你的代碼,最簡單的解決方法就是將胖逗號改成普通的逗號,而後在引用左邊的參數。或者,你能夠將方法的接口改成接受一個哈希,一個比較好的解決方式就是將方法的接口改成指望 Pair,然而,這須要你當即改動全部的方法調用代碼。
# Perl 5 sub get_the_loot { my $loot = shift; my %options = @_; # ... } # 注意 這個方法調用中沒有使用花括號 get_the_loot('diamonds', quiet_level => 'very', quantity => 9); # Perl 6,原始接口 sub get_the_loot($loot, *%options) { # * 意味着接受任何東西 # ... } get_the_loot('diamonds', quiet_level => 'very', quantity => 9); # 注意 這個方法調用中沒有使用花括號 # Perl 6中,接口改成指定有效的選項 # sigil 前面的冒號表明指望一個 Pair # 參數的鍵名字和變量相同 sub get_the_loot($loot, :$quiet_level?, :$quantity = 1) { # 這個版本會檢查未指望的參數 # ... } get_the_loot('diamonds', quietlevel => 'very'); # 參數名字拼寫錯誤,將會拋出一個錯誤
如今使用兩個問號替代了本來的一個問號,冒號被兩個歎號替代了。
my $result = ($score > 60) ? 'Pass' : 'Fail'; # Perl 5 my $result = ($score > 60) ?? 'Pass' !! 'Fail'; # Perl 6
被波浪線替代。
小貼士:想象一下使用針和線「縫合」兩個字符串。
$food = 'grape' . 'fruit'; # Perl 5 $food = 'grape' ~ 'fruit'; # Perl 6
在 Perl 5,x
是重複運算符。
在標量上下文,x
將會重複一個字符串,在 Perl 6裏,x
會在任何上下文重複字符串。
在列表上下文,x
當且僅當將列表括入圓括號中時重複當前列表,在 Perl 6,新的運算符xx
將會在任何上下文重複列表。
小貼士:xx相對於x是比較長的,因此xx適用於列表。
# Perl 5 print '-' x 80; # 打印出一行橫槓 @ones = (1) x 50; # 一個含有80個1的列表 @ones = (5) x ones; # 把全部元素設爲5 # Perl 6 print '-' x 80; # 無變化 @ones = 1 xx 80; # 再也不須要圓括號 @ones = 5 xx @ones; # 再也不須要圓括號
在 Perl 5,..
依賴於上下文是兩個徹底不一樣的運算符。
在列表上下文,..
是熟悉的範圍運算符,範圍運算在 Perl 6有許多新的改變,不過 Perl 5的範圍運算代碼不須要翻譯。
在標量上下文,..
和...
是不爲人知的翻轉運算符,在 Perl 6中它們被ff
和fff
取代了。
在 Perl 5,"${foo}s"
將變量名從普通的文本中分離出來,在 Perl 6中,簡單的將花括號擴展到 sigil 外便可:"{$foo}s"
。
除了條件語句兩邊的括號如今是可選的,這些關鍵字幾乎沒有變化,可是若是要使用括號,必定沒關係跟着關鍵字,不然這會被看成普通的函數調用,綁定條件表達式到一個變量也稍微有點變化:
if (my $x = dostuff()) { ... } # Perl 5 if dostuff() -> $x { ... } # Perl 6
在 Perl 6中你能夠繼續使用my
格式,可是它的做用域再也不位於語句塊的內部,而是外部。
在 Perl 6中unless
條件語句只容許單個語句塊,不容許elsif
或者else
子語句。
given-when
結構相似於if-elsif-else
語句或者 C 裏面的switch-case
結構。它的普通樣式是:
given EXPR { when EXPR { ... } when EXPR { ... } default { ... } }
根據這個最簡單的樣式,有以下代碼:
given $value { when "a match" { do-something(); } when "another match" { do-something-else(); } default { do-default-thing(); } }
這是在when
語句中簡單的使用標量匹配的場景,更廣泛的實際狀況都是利用如正則表達式通常的複雜的實體等替代標量數據對輸入數據進行智能匹配。
同時參閱文章上面的智能匹配操做。
除了循環條件兩邊的括號如今是可選的,這些關鍵字幾乎沒有變化,可是若是要使用括號,必定沒關係跟着關鍵字,不然這會被看成普通的函數調用,綁定條件表達式到一個變量也稍微有點變化:
while (my $x = dostuff()) { ... } # Perl 5 while dostuff() -> $x { ... } # Perl 6
在 Perl 6中你能夠繼續使用my
格式,可是它的做用域再也不位於語句塊的內部,而是外部。
注意對文件句柄按行讀取發生了變化。
在 Perl 5,這能夠利用鑽石運算符在while
循環裏面完成,若是使用for
替代while
則會有一個常見的bug,由於for
致使文件被一次性讀入,使程序的內存使用變的糟糕。
在 Perl 6,for
語句是緩式的(lazy),因此咱們能夠在for
循環裏面使用.lines
方法逐行讀取文件:
while (<IN_FH>) { ... } # Perl 5 for $IN_FH.lines { ... } # Perl 6
首先注意這有一個常見的對for
和foreach
關鍵字的誤解,許多程序員認爲它們是把 C-風格for 和列表迭代方式區分開來,然而並非!實際上,它們是可互換的,Perl 5的編譯器經過查找後面的分號來決定解析成哪種循環。
C-風格的for循環如今使用loop
關鍵字,其它都沒有變化,兩邊的括號是必須的:
for (my $i = 1;$i <= 10;$i++) { ... } # Perl 5 loop (my $i = 1;$i <= 10;$i++) { ... } # Perl 6
for
或者foreach
的循環迭代樣式如今統一叫作for
,foreach
再也不是一個關鍵字,括號是可選的。
迭代變量,若是有的話,已經從列表的前部移動到列表的後面,變量以前還有加上箭頭運算符。
迭代變量,如今是詞法變量,my
已經再也不須要並且不容許使用。
在 Perl 5裏,迭代變量是當前列表中元素的可讀寫別名。
在 Perl 6,這個別名默認是隻讀的(爲了安全),除非你將->
改成<->
。當翻譯的時候,檢查循環變量的使用來決定是否須要可讀寫。
for my $car (@cars) { ... } # Perl 5,可讀寫 for @cars -> $car { ... } # Perl 6,只讀 for @cars <-> $car { ... } # Perl 6,可讀寫
若是使用默認的變量$_
,可是又須要可讀寫,那麼須要使用<->
並顯示指定變量爲$_
。
for (@cars) { ... } # Perl 5,默認變量 for @cars { ... } # Perl 6,$_ 是隻讀的 for @cars <-> $_ { ... } # Perl 6,$_ 可讀寫
這是 Perl 6中和 Perl 5 while...each(%hash)
或者while...each(@array)
(遍歷數據結構的鍵或者索引和值)等同的用法:
while (my ($i, $v) = each(@array)) { ... } # Perl 5 for @array.kv -> $i, $v { .... } # Perl 6 while (my ($k, $v) = each(%hash)) { ... } # Perl 5 for %hash.kv -> $k, $v { ... } # Perl 6
無變化的:
next
last
redo
continue
語句塊已經被去掉了,做爲替代,在循環體中使用NEXT
語句塊:
# Perl 5 my $str = ''; for (1..5) { next if $_ % 2 == 1; $str .= $_; } continue { $str .= ':'; } # Perl 6 my $str = ''; for 1..5 { next if $_ % 2 == 1; $str ~= $_; NEXT { $str ~= ':'; } }
內建函數以前接受一個裸露的代碼塊,沒有逗號在其餘參數以前,如今須要在塊和參數之間插入一個逗號,好比map
,grep
等等。
my @result = grep { $_ eq "bars" } @foo; # Perl 5 my @result = grep { $_ eq "bars" }, @foo; # Perl 6
my $deleted_value = delete $hash{$key}; # Perl 5 my $deleted_value = %hash{$key}:delete; # Perl 6,使用 :delete 副詞 my $deleted_value = delete $array[$i]; # Perl 5 my $deleted_value = @array[$i]:delete; # Perl 6,使用 :delete 副詞
say "element exists" if exists $hash{$key}; # Perl 5 say "element exists" if %hash{$key}:exists; # Perl 6,使用 :exists 副詞 say "element exists" if exists $array[$i]; # Perl 5 say "element exists" if @array[$i]:exists; # Perl 6,使用 :exists 副詞
在 Perl 5對變量的匹配和替換是使用=~
正則綁定運算符完成的。
在 Perl 6中使用智能匹配運算符~~
替代。
next if $line =~ /static/; # Perl 5 next if $line ~~ /static/; # Perl 6 next if $line !~ /dynamic/; # Perl 5 next if $line !~~ /dynamic/; # Perl 6 $line =~ s/abc/123/; # Perl 5 $line ~~ s/abc/123/; # Perl 6
一樣的,新的.match
方法以及.subst
方法能夠被使用。注意.subst
是不可變操做,參見S05/Substitution。
將全部的副詞的位置從尾部移動到了開始,這可能須要你爲普通的匹配好比/abc/
添加可選的m
。
next if $line =~ /static/i; # Perl 5 next if $line ~~ m:i/static/; # Perl 6
若是實際的正則表達式比較複雜,你可能不想作修改直接使用,那麼就加上P5
副詞吧。
next if $line =~ m/[aeiou]/; # Perl 5 next if $line ~~ m:P5/[aeiou]/; # Perl 6,使用 :P5 副詞 next if $line ~~ /<[aeiou]>/; # Perl 6,新的風格
Perl 5的正則語法支持不少特殊的匹配語法,它們不會所有列在這裏,可是通常在斷言中做爲()
的替代的是<>
。
對於字符類,這意味着:
Perl 5 Perl 6 [abc] <[abc]> [^abc] <-[abc]> [a-zA-Z] <[a..zA..Z]> [[:upper:]] <:Upper> [abc[:upper:]] <[abc]+:Upper>
對於環視(look-around)斷言:
Perl 5 Perl 6 (?=[abc]) <?[abc]> (?=ar?bitray* pattern) <before ar?bitray* pattern> (?!=[abc]) <![abc]> (?!=ar?bitray* pattern) <!before ar?bitray* pattern> (?<=ar?bitray* pattern) <after ar?bitray* pattern> (?<!=ar?bitray* pattern) <!after ar?bitray* pattern> (跟<>語法無關,環視語法`/foo\Kbar/`變成了`/foo<(bar)>/` (?(?{condition})yes-pattern|no-pattern) [ <?{condition}> yes-pattern | no-pattern ]
在 Perl 6的正則中,|
用於LTM,也就是根據一組基於模糊匹配規則從結果中選擇一個最優的結果,而不是位置優先。
對於 Perl 5代碼最簡單解決方案就是使用||
替代|
。
對於更多的規則,同時使用來自Blue Tiger的translate_regex.pl
。
嚴格模式如今是默認的。
警告如今默認是開啓的。no warnings
目前仍是NYI狀態,可是把語句放到quietly {}
塊以內就能夠避免警告。
這個功能可讓程序在發生錯誤拋出異常,如今 Perl 6默認拋出異常,除非你顯式的測試返回值。
# Perl 5 open my $i_fh, '<', $input_path; # 錯誤時保持沉默 use autodie; open my $o_fh, '>', $output_path; # 錯誤時拋出異常 # Perl 6 my $i_fh = open $input_path, :r; # 錯誤時拋出異常 my $o_fh = open $output_path, :w; # 錯誤時拋出異常
如今use base
和use parent
已經被 Perl 6中的is
關鍵字取代,在類的聲明中。
# Perl 5 package Cat; use base qw (Animal); # Perl 6 class Cat is Animal;
再也不相關。Int
如今是無限精度的,是Rat
類型的分子(分母最大能夠是2**64,出於性能考慮以後會自動轉換爲Num
類型)。若是你想使用無限精度分母的Rat
,那麼FatRat
顯然是最適合的。
constant
在 Perl 6用來變量聲明,這相似與my
,不過變量會鎖定保持第一次初始化的值不變(在編譯時期求值)。
因此,將=>
改成=
,並加上一個 sigil。
use constant DEBUG => 0; # Perl 5 constant $DEBUG = 0; # Perl 6 use constant pi => 4 * atan2(1, 1); # Perl 5 # pi, e, i都是 Perl 6的內建變量
容許使用非ASCII或者非UTF8編碼編寫代碼。
Perl的編譯指示,使用整數運算替代浮點。
在編譯時期操做 @INC。
再也不相關。
在 Perl 6中,方法調用如今使用 C3 方法調用順序。
再也不相關。
在 Perl 6中,源代碼將使用utf8編碼。
在 Perl 5中被取代,參見vars。
在翻譯到 Perl 6代碼以前,你可能須要重構你的代碼移除對use vars
的使用。
參見S19/commandline。
未變化的:
-c -e -h -I -n -p -S -T -v -V
在Spec中沒有變化,可是在Rakudo中沒有實現。
如今你須要手動調用.split
。
在Spec中沒有變化,可是在Rakudo中沒有實現。
如今你須要手動調用.split
。
如今默認提供此行爲。
只有-M
還存在,還有,你們能夠再也不使用「no Module」語法了,-M
的「no」模塊操做再也不可用。
由於全部的特性都已經開啓,請使用小寫的-e
。
被++BUG
元語法替代。
開關選項解析如今被MAIN
子方法的參數列表替代。
# Perl 5 #!/usr/bin/perl -s if ($xyz) { print "$xyz\n" } ./example.pl -xyz=5 5 # Perl 6 sub MAIN(Int :$xyz) { say $xyz if $xyz.defined; } perl6 example.p6 --xyz=6 6 perl6 example -xyz=6 6
如今尚未指定。
移除,參見S19/commandline。
如今默認開啓。
在 Perl 5,讀取文本文件的行一般是這樣子:
open my $fh, '<', "file" or die "$!"; my @lines = <$fh>; close $fh;
在 Perl 6,這簡化成了這樣:
my @lines = "file".IO.lines;
不要嘗試一次讀入一個文件,而後使用換行符分割,由於這會致使數組尾部含有一個空行,比你想象的多了一行(它實際更復雜一些)。好比:
# 初始化要讀的文件 spurt "test-file", q:to/END/; first line second line third line END # 讀取 my @lines = "test-file".IO.slurp.split(/\n/); say @lines.elems; # 輸出 4
鑑於 Perl 5你可能這麼作:
my $arg = 'Hello'; my $captured = \`echo \Q$arg\E\`; # 注意反引號\` my $captured = qx(echo \Q$arg\E);
或者使用String::ShellQuote(由於\Q...\E不是徹底正確的):
my $arg = shell_quote 'Hello'; my $captured = 'echo $arg'; my $captured = qx(echo $arg);
在 Perl 6中你可能不想經過shell運行命令:
my $arg = 'Hello'; my $captured = run('echo', $arg, :out).out.slurp-rest; my $captured = run(«echo "$arg"», :out).out.slurp-rest;
若是你想也可使用shell:
my $arg = 'Hello'; my $captured = shell("echo $arg", :out).out.slurp-rest; my $captured = qqx{echo $arg};
可是小心這種狀況徹底沒有保護,run
不使用shell執行命令,因此不須要對參數進行轉義(直接進行傳遞)。若是你使用shell
或者qqx
,那麼全部東西都會做爲一個長長的字符串傳給shell,除非你當心的驗證你的參數,頗有可能由於這樣的代碼引入shell注入漏洞。
在 Perl 5中能夠指定 Perl 模塊的額外的搜索路徑的一個環境變量是PERL5LIB
:
$ PERL5LIB="/some/module/lib" perl program.pl
在 Perl 6中也相似,僅僅須要改變一個數字,正如你想的那樣,你只需使用PERL6LIB
:
$ PERL6LIB="/some/module/lib" perl6 program.p6
就 Perl 5來講,若是你不指定PERL5LIB
,你須要使用use lib
編譯指示來指定庫的路徑:
use lib '/some/module/lib'
注意PERL6LIB
在 Perl 6中更多的是給開發者提供便利(與 Perl 5中的PERL5LIB
相對應),模塊的用戶不要使用由於將來它可能被刪除,這是由於 Perl 6的模塊加載沒有直接兼容操做系統的路徑。
不像 Perl 5,一個只包含('0')的字符串是 True
,做爲 Perl 6的核心類型,它有着更多的意義,這意味着常見的模式:
... if defined $x and length $x; # 或者現代 Perl 的寫法 length($x)
在 Perl6裏面變的更爲簡化:
... if $x;
被移除。
Perl 6的設計容許自動的保存加載編譯的字節碼。
Rakudo目前只支持模塊。
在 Perl 5你能夠像這樣有選擇性的導入一個給定模塊的函數:
use ModuleName qw{foo bar baz};
在 Perl 6,一個想要被導出的函數須要對相關的方法使用is export
,全部使用is export
的方法都會被導出,所以,下面的模塊Bar
導出了方法foo
和bar
,沒有導出baz
:
unit module Bar; sub foo($a) is export { say "foo $a" } sub bar($b) is export { say "bar $b" } sub baz($z) { say "baz $z" }
使用模塊時,簡單的use Bar
便可,如今函數foo
和bar
都是可用的:
use Bar; foo(1); # 輸出 "foo 1" bar(2); # 輸出 "bar 2"
若是你嘗試調用baz
函數,會在編譯時報出「未定義的例程」錯誤。
因此,如何像 Perl 5那樣可選擇性的導入一個模塊的函數呢?支持這個你須要在模塊中定義EXPORT
方法來指定導出和刪除module Bar
的聲明(注意在Synopsis 11中並無module
語句,然而它能夠工做) 。
模塊Bar
如今僅僅是一個叫作Bar.pm
的文件並含有如下內容:
use v6; sub EXPORT(*@import-list) { my %exportable-subs = '&foo' => &foo, '&bar' => &bar,; my %subs-to-export; for @import-list -> $sub-name { if grep $sub-name, %exportable-subs.keys { %subs-to-export{$sub-name} = %exportable-subs{$sub-name}; } } return %subs-to-export; } sub foo($a) { say "foo $a" } sub bar($b) { say "bar $b" } sub baz($z) { say "baz $z" }
注意如今方法已再也不使用is export
顯式的導出,咱們定義了一個EXPORT
方法,它指定了模塊能夠被導出的方法,而且生成一個包含實際被導出的方法的哈希,@import-list
是調用代碼中使用set
語句設置的,這容許咱們可選擇性的導出模塊中可導出的方法。
因此,爲了只導出foo
例程,咱們能夠這麼使用:
use Bar <foo>; foo(1); # 輸出 "foo 1"
如今咱們發現即便bar
是可導出的,若是咱們沒有顯式的導出它,它就不會可用,所以下面的代碼在編譯時會引發「未定義的例程」錯誤:
use Bar <foo>; foo(1); bar(5); # 報錯 "Undeclared routine: bar used at line 3"
然而,咱們能夠這樣:
use Bar <foo bar>; foo(1); # 輸出 "foo 1" bar(5); # 輸出 "bar 5"
注意,baz
依然是不可導出的即便使用use
指定:
use Bar <foo bar baz>; baz(3); # 報錯 "Undeclared routine: baz used at line 2"
爲了使這個能正常工做,顯然須要跨越許多的障礙,在使用標準use的狀況下,經過使用is export
指定某一個函數是導出的,Perl 6會自動以正確的方式建立EXPORT
方法,因此你應該仔細的考慮建立一個本身的EXPORT
方法是否值得。
在 Perl 5,Data::Dumper模塊被用來序列化,還有程序員調試的時候用來查看程序數據結構的內容。
在 Perl 6中,這個任務徹底被存在於每個對象的.perl
方法替代。
# 給定 my @array_of_hashes = ( {NAME => 'apple', type => 'fruit'}, {NAME => 'cabbage', type => 'no, plese no'}, ); # Perl 5 use Data::Dumper; $Data::Dumper::Useqq = 1; print Dumper \@array_of_hashes; # 注意反斜槓 # Perl 6 say @array_of_hashes.perl; # .perl會做用在數組而不是引用上面
在 Perl 5,Data::Dumper有着更復雜的可選的調用約定,它支持對變量命名。
在 Perl 6,將一個冒號放在變量的 sigil 前面轉換它爲 Pair,Pair 的鍵是變量的名字,值是變量的值。
#給定 my ($foo, $bar) = (42, 44); my @baz = (16, 32, 64, 'Hike!'); # Perl 5 use Data::Dumper; print Data::Dumper->Dump( [$foo, $bar, \@baz], [qw(foo bar *baz )], ); # 輸出 $foo = 42; $bar = 44; @baz = ( 16, 32, 64, 'Hike!' ); # Perl 6 say [ :$foo, :$bar, :@baz ].perl; # 輸出 ["foo" => 42, "bar" => 44, "baz" => [16, 32, 64, "Hike!"]]
開關選項解析如今被MAIN
子方法的參數列表替代。
# Perl 5 use 5.010; use Getopt::Long; GetOptions( 'length=i' => \(my $length = 24), # 數值 'file=s' => \(my $data = 'file.data'), # 字符串 'verbose' => \(my $verbose), # 標誌 ) or die; say $length; say $data; say 'Verbosity', ($verbose ? 'on' : 'off') if defined $verbose; perl example.pl 24 file.data perl example.pl --file=foo --length=42 --verbose 42 foo Verbosity on perl example.pl --length=abc Value "abc" invalid for option length (number expected) Died at c.pl line 3. # Perl 6 sub MAIN (Int :$length = 24, :file($data) = 'file.data', Bool :$verbose) { say $length if $length.defined; say $data if $data.defined; say "Verbosity", ($verbose ?? 'on' !! 'off'); } perl6 example.p6 24 file.dat Verbosity off perl6 example.p6 --file=foo --length=42 --verbose 42 foo Verbosity on perl6 example.p6 --length=abc Usage: example.p6 [--length=<Int>] [--file=<Any>] [--verbose]
注意 Perl 6會在命令行解析出錯時自動生成一個完整的用法信息。
一個快速的將 Perl 5代碼翻譯爲 Perl 6代碼的途徑就是經過自動化翻譯。
注意:這些翻譯器都尚未完成。
本項目的目致力於自動現代化 Perl 代碼,它沒有一個 web 前端,因此必須本地安裝使用,它還含有一個單獨的程序用來將 Perl 5的正則轉換爲 Perl 6的版本。
https://github.com/Util/Blue_Tiger/。
在線翻譯器。
本項目是一套 Perl 跨平臺編譯器,包含 Perl 5到 Perl 6的翻譯,它有一個 web 前端,因此能夠在不安裝的前提下使用,它目前只支持 Perl 5語法的一個子集。
http://www.perlito.org/perlito/perlito5to6.html。
Larry Wall 本身用來翻譯 Perl 5到 Perl 6的代碼已經太老了,在目前的 Perl 5版本中已經不可用了。
MAD(Misc Attribute Definition)是一個經過源碼構建 Perl 的時候可用的配置選項, perl\
執行程序分析並翻譯你的 Perl 代碼到 op-tree,經過遍歷 op-tree執行你的程序。一般,這些分析的細節會在處理的時候丟掉,當MAD開啓的時候,`perl`執行程序會把這些細節保存成XML文件,而後MAX解析器即可以讀取它並進一步處理成 Perl 6的代碼。
爲了進行你的MAD實驗,請前去 #perl6 頻道請教最適合的 Perl 5 版本。
Jeff Goff的圍繞 Perl::Critic 框架的用於 Perl 5的模塊 Perl::ToPerl6 ,目標是最最小的修改並將 Perl 5的代碼轉換成可編譯的 Perl 6代碼,代碼的轉換器是可配置和插件化的,你能夠經過它建立本身的轉換器,根據你的需求自定義存在的轉換器。你能夠從CPAN上面獲取最新的版本,或者 follow 發佈在 GitHub 的工程,在線轉換器可能在某一天會可用。