[情報] Perl 的 Destructuring assignment~ ^^

看板Perl作者 (Cindy Wang)時間10年前 (2014/08/13 17:20), 編輯推噓3(305)
留言8則, 5人參與, 最新討論串1/1
Perl 現在可以對複雜結構作 destructuring assignment 了 ^^ 我最近寫了一個叫作 DestructAssign 的 mod 丟到 cpan 上面, 用法大概是這樣: use DestructAssign qw(des des_alias); 在函數 des 後面放一個 [...] 或 {...} (anonymous array 或是 anonymous hash), 裡面可以放一些準備接資料的變數, 這樣就做成一個可以 match 資料結構的 pattern. 然後就可以拿 = 指定一個形狀類似的資料給它, 那麼放在 pattern 裡面的變數們就會接到資料了. 實際例子像這樣: my($w, $x, $y, $z); des [$x, [undef, {y => $y}, undef, $w], $z] = [2, [25, {x => 'x', y => 3}, 26, 1], 4]; # got ($w, $x, $y, $z) = (1, 2, 3, 4) # 資料結構可以是遞迴巢狀的 # array pattern 可以放 undef 來跳過你不想拿的欄位 # hash pattern 裡面 # 是 value 的部分可以放接資料的變數 # key 的部分是用來指定要拿 data 對應的 hash 中 # 哪一個 key 的 value des [3 => $w, $x, -2 => $y, $z] = [1..9]; # got ($w, $x, $y, $z) = (4, 5, 8, 9) # 在 array pattern 裡面也可以直接指定要拿的 index # 也依 perl 習慣, 負的 index 表示從尾巴拿 my(@array, %hash); des [3 => @array, -4 => %hash] = [1..8]; # got @array = (4..8), %hash = (5 => 6, 7 => 8) # 在 array pattern 裡面放 @array 或 %hash 變數的話 # 它會取得從那時的位置開始之後的所有資料 # 比起傳統的 my($a, $b, @remain) = (1,2,3,4,5); # 3,4,5 給了 @remain 之後如果還想再用別的變數拿其中的東西, # 可以再用指定 index 的方式重拿 :p des {x => $x, x => [$y, $z]} = {x => [1, 2]}; # got $x = [1,2], $y = 1, $z = 2 # 如果某個資料欄位是一個複雜的結構, # 你又想用一個變數拿它整個, 又想拿別的變數拿它其中一部分, # 可以重複指定同樣的 key 多拿幾次. # 就算是 hash pattern 也可以用重複的 key my $data = [1, 2, 3]; des_alias [undef, $x] = $data; $x = 20; # got $data = [1, 20, 3] # des_alias 和 des 的差別是, des 是把 data 的值 copy 給變數 # 而 des_alias 是把變數變成 data 的 alias # 從此對接收變數的讀寫動作都會直接反應在 data 上 # 由於「黏上」的變數不太方便斷開魂結 # 所以建議直接 my 新的變數來黏, 或是對 package var 的話用 local 的 # 出了 block 以後就可以自動塵歸塵土歸土 { des [my($i, $j), { k => my $k }] = [1, 2, {k => 3}]; # got my($i, $j, $k) = (1, 2, 3) # 這個是一邊作 destruct assign 一邊 my 接收變數的示範用法 } my $oo; my $data = [1,2,3]; { des_aliasmy [$oo] = $data; $oo = 5; # got $data = [5,2,3]; } # got $oo = undef; # 外面的 $oo 沒有黏到 $data $oo = 6; # got $data [5,2,3]; # 存取外面的 $oo 不會影響 $data 的內容 詳細的說明可以看 cpan 或 metacpan 或 github, 如果有遇到 bug, 或是有覺得哪種長相的 pattern 應該也很實用但我沒做, 都歡迎跟我討論 ^^ 在 ptt 這邊或是 github 上面, 或是 perl RT 都可以~ 目前我測試過能用的 perl 版本有: 5.8.9, 5.10.1, 5.12.5, 5.14.4, 5.16.3, 5.18.2, 5.20.0 5.8.5 還不能用 接下來我想做的有 讓它在 5.8.5 可以用, 加上「取 reference」(就是 \ ) 的 pattern, 把指定 index 和 key 的 constant 在 compile time 預作處理, 因為就算是 constant, perl 的 scalar overhead 還是蠻多的, 有一塊效能可以偷, 還有 hash key 的 hash 值也可以預先計算. cpan: http://search.cpan.org/~cindy/DestructAssign/lib/DestructAssign.pm metacpan: https://metacpan.org/pod/DestructAssign github: https://github.com/CindyLinz/Perl-DestructAssign -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 112.121.80.249 ※ 文章網址: http://www.ptt.cc/bbs/Perl/M.1407921627.A.B3E.html

08/14 00:15, , 1F
推阿
08/14 00:15, 1F

08/14 12:34, , 2F
why support 5.8.5 www
08/14 12:34, 2F

08/14 12:49, , 3F
好問題.. 囧
08/14 12:49, 3F

08/14 14:52, , 4F
該不會是你們家... XD
08/14 14:52, 4F

08/14 15:25, , 5F
應該沒有..XD 是 cpan tester 有列到的關係 ^^|
08/14 15:25, 5F

08/14 17:59, , 6F
推!
08/14 17:59, 6F

08/15 12:23, , 7F
喔喔 XDDDDDD
08/15 12:23, 7F

08/15 16:14, , 8F
本人不錯看
08/15 16:14, 8F
文章代碼(AID): #1JwotRi- (Perl)
文章代碼(AID): #1JwotRi- (Perl)