[情報] Perl 的 Destructuring assignment~ ^^

作者: CindyLinz (Cindy Wang)   2014-08-13 17:20:24
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
作者: abliou (愚者)   2014-08-14 00:15:00
推阿
作者: xatier (一切重來就好了...)   2014-08-14 12:34:00
why support 5.8.5 www
作者: CindyLinz (Cindy Wang)   2014-08-14 12:49:00
好問題.. 囧
作者: xatier (一切重來就好了...)   2014-08-14 14:52:00
該不會是你們家... XD
作者: CindyLinz (Cindy Wang)   2014-08-14 15:25:00
應該沒有..XD 是 cpan tester 有列到的關係 ^^|
作者: skenbo0916 (凱凱)   2014-08-14 17:59:00
推!
作者: xatier (一切重來就好了...)   2014-08-15 12:23:00
喔喔 XDDDDDD
作者: herculus6502 (金麟豈是池中物)   2014-08-15 16:14:00
本人不錯看

Links booklink

Contact Us: admin [ a t ] ucptt.com