- 论坛徽章:
- 0
|
这几天被一个诡异的bug坑得死去活来,刚刚终于找出问题所在,让我对于map的写法有了更清楚的认识。
其实本不是什么高深的知识,我也不是什么perl高手。只是跟大家分享一下心得。
问题起源于一个乘法始终得不到正确结果:
- use List::Util qw(product);
- my @a = ("A","B","C");
- my %h = ("A"=>0.1, "B"=>0.2, "C"=>0.3);
- my $p = product(
- map{$h{$_}}(@a),
- 10
- );
复制代码 我的本意应该是0.1*0.2*0.3*10 = 0.06
可结果总为0
由于原本整个程序比较长,算法有些复杂,那个哈希的键其实是个相当复杂的表达式,我花了很多时间来确认由数组@a输出的list内不含有0
然后我终于基本确定由@a输出的list里肯定不含有0,我说这可奇了怪了!但当我尝试把map那句后面加上:
- product(
- map{$h{$_}}(@a) || 1,
- 10
- );
复制代码 输出神奇的不为0了。
我勒个去,这tm什么鬼???!!!
不过当我我验算了这输出的数据后,发现输出不是预期值。。。。。。艹艹艹
然后我开始疯狂的怀疑这个版本的list::util模块的product函数有bug,换了个perl版本,换了个机器验证。结果依然如故。。。
最后没办法了,我开始不断地向map中代入不同的数值内容以观察其输出:
- product(
- map{$_+1}(1..4),
- 0.9
- );
复制代码 发现这个输出的是228,于是乎突然间意识到到底是发生了什么!
狗x的!map把小括号外面逗号后面的0.9也代了进去!!!!!
说好的小括号限定函数操作内容呢???!!!
然后我马上就回忆起了以前在文档里看过的map另一种表达方式 map EXPR,LIST:
@chars = map(chr, @numbers);
不过文档里和书里写map BLOCK LIST 这种表达方式的时候都是这么写:
my @squares = map { $_ * $_ } @numbers;
所以我一直以为在这种写法中,要加括号的话就给后面的list加就行了,没想到中招了。
在map BLOCK LIST这种写法中要加括号限定map操作内容的话应该这么加:
my @squares = map({ $_ * $_ } @numbers);
- product(
- map({$_+1}(1..4)),
- 0.9
- );
复制代码 如此,得到了预期结果108.
改好了程序之后回头想一想,其实还有几个不明确的地方。
一是map的大括号BLOCK部分到底是算个什么成分?本质上它也就是map的第一个参数吗?
二是我在中间改的
- product(
- map{$h{$_}}(@a) || 1,
- 10
- );
复制代码 这个代码得到的输出到底是怎么算的呢?好像是||操作符把@a转换成了scalar,然后不是0的话,就scalar@a和10两个标量元素的列表被带入map的BLOCK中进行输出。
不知道我的理解对不对?
|
|