[情报] 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