免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: py
打印 上一主题 下一主题

函数在返回数组的时候遇到了问题。。。大家都来看看:) [复制链接]

论坛徽章:
0
31 [报告]
发表于 2010-08-06 09:01 |只看该作者
这里要说到一个机制,记得数组@aa=(1..1000000000)这样会占用很大的存储空间吗?
如果我们用for(1..100000000000)却不存在这问题。这是因为:
but you should be aware that the ".." operator creates an array of all integers in the range.  This can
       take a lot of memory for large ranges.  Instead use:

           @results = ();
           for ($i=5; $i < 500_005; $i++) {
               push(@results, some_func($i));
           }

       This situation has been fixed in Perl5.005. Use of ".." in a "for" loop will iterate over the range, with-
       out creating the entire range.

           for my $i (5 .. 500_005) {
               push(@results, some_func($i));
           }

       will not create a list of 500,000 integers.


Perl在5.005.版本之后对for做了优化。所以只占用一个地址位。


而for (qw(1 2 3 4)){..}这个之所以会占用两个地址,是因为perl的内存回收机制。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
32 [报告]
发表于 2010-08-06 09:19 |只看该作者
正如我所料

sub func2 :lvalue
{
        my @ar = qw/a b c/;
        @ar;
}

虽然func2是返回array了,但是
...
黑色阳光_cu 发表于 2010-08-05 14:57


我觉得,一个正常的函数在做return @array;的时候就是返回了一个数组。
不能说func2返回的不是数组,但是,我认为lvalue的行为是特殊,具体可以看文档perlsub部分。
按照文档所说,lvalue出现的意义是“It is possible to return a modifiable value from a subroutine.”

  1. my $val;
  2. sub canmod : lvalue {
  3.         $val;
  4. }
  5. sub nomod {
  6.         $val;
  7. }

  8. canmod() = 5; # assigns to $val
  9. nomod() = 5; # ERROR
复制代码
运行的时候提示Can't modify non-lvalue subroutine call in scalar assignment
这么看来一般函数的返回值,在scalar context下是不能修改的。

shift(func());报错是在“编译期间”报错,这个是非常明确的,perl会清楚的提示“aborted due to compilation errors”
既然如此,那shift的报错就和很多细节都没关系了,可能词法分析就没通过,所以要用dugu072_cu说的shift( @{ [ &func ] } );

黑色阳光_cu 是对的。编译不通过是因为:
shift(func()); 失败是因为shift的参数只能是array.而不是一个表 ...
toniz 发表于 2010-08-05 15:44

qw/1 2 3/是常量,铁定不能修改的。
我也觉得函数的返回值是可以修改的。lvalue的例子只说明在scalar context下不能修改。

黑色阳光_cu 的 warn \func(); ,说明了 return 确实是返回 list;但结合你给的代码,反而很难理 ...
dugu072_cu 发表于 2010-08-05 17:02

当return @abc;的时候,返回值是array。

回复  toniz


    为什么qw是value呢?qw(1 2 3)和(1..3)的区别呢?
yybmsrs 发表于 2010-08-05 18:06

看见这样的结果真让人难以接受。。。
我觉得这俩东西是一样的。但看来还是有区别,qw(1 2 3)是常量。(1..3)是产生的list,为什么就不算常量了...?

论坛徽章:
0
33 [报告]
发表于 2010-08-06 09:20 |只看该作者
在for语句中不算,但拿出来赋值还是算

论坛徽章:
0
34 [报告]
发表于 2010-08-06 09:21 |只看该作者
这里只是因为PERL针对FOR语句的优化

论坛徽章:
0
35 [报告]
发表于 2010-08-06 09:40 |只看该作者
我觉得,一个正常的函数在做return @array;的时候就是返回了一个数组。
不能说func2返回的不是数组,但 ...
py 发表于 2010-08-06 09:19



    perldoc -q "a list and an array"

What is the difference between a list and an array?
  An array has a changeable length. A list does not. An array is something
  you can push or pop, while a list is a set of values. Some people make
  the distinction that a list is a value while an array is a variable.
  Subroutines are passed and return lists, you put things into list
  context, you initialize arrays with lists, and you "foreach()" across a
  list. "@" variables are arrays, anonymous arrays are arrays, arrays in
  scalar context behave like the number of elements in them, subroutines
  access their arguments through the array @_, and "push"/"pop"/"shift"
  only work on arrays.

  As a side note, there's no such thing as a list in scalar context. When
  you say

          $scalar = (2, 5, 7, 9);

  you're using the comma operator in scalar context, so it uses the scalar
  comma operator. There never was a list there at all! This causes the
  last value to be returned: 9.

我是看过这段话,所以一直记得,return 的是 list ……

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
36 [报告]
发表于 2010-08-06 09:54 |只看该作者
perldoc -q "a list and an array"

What is the difference between a list and an array?
  ...
dugu072_cu 发表于 2010-08-06 09:40


恩。。。文档中关于return里也是这么说的,说返回的是list
你看这篇http://japhy.perlmonk.org/articles/pm/2000-02.html
最后的Return Values有例子在解释,我觉得说的也有道理。

论坛徽章:
0
37 [报告]
发表于 2010-08-06 09:54 |只看该作者
本帖最后由 toniz 于 2010-08-06 10:04 编辑

我也来提个问题,看下面的代码:
  1. for my $aa(qw(1 2 3 4)){
  2. #        $aa=1234;
  3.         ${\$aa}=1234;
  4. }
复制代码
这样运行正常。去掉第一句的注释,就报错。。

$aa是只读的,而\$aa指向的变量却是可写的。
也就是说\$aa并不是$aa的引用。晕不。。。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
38 [报告]
发表于 2010-08-06 11:25 |只看该作者
我也来提个问题,看下面的代码:这样运行正常。去掉第一句的注释,就报错。。

$aa是只读的,而\$aa指向的 ...
toniz 发表于 2010-08-06 09:54



\$aa为什么不是$aa的引用?
  1. foreach my $aa(qw(1 2 3 4)){
  2.     my $bb = \$aa;
  3.     $bb = 10;
  4.     print "$bb\n";
  5. }
复制代码
$bb是$aa的引用,所以$bb肯定是可写的。

论坛徽章:
0
39 [报告]
发表于 2010-08-06 11:31 |只看该作者
本帖最后由 toniz 于 2010-08-06 11:36 编辑

不一样的, ${\$aa}=1234;是想对$aa赋值。
而你的 $bb = 10;是对$b赋值。

看下面代码:
  1. $aa=123;
  2. ${\$aa}=1;
  3. print "$aa\n";

  4. $aa=123;
  5. $bb=\$aa;
  6. $bb=1;
  7. print "$aa\n";
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
40 [报告]
发表于 2010-08-06 13:07 |只看该作者
不一样的, ${\$aa}=1234;是想对$aa赋值。
而你的 $bb = 10;是对$b赋值。

看下面代码:
toniz 发表于 2010-08-06 11:31



是的,是我错了。

我又仔细看了你之前的代码

  1. for my $aa(qw(2)){
  2.         ${\$aa}=1234;
  3. }
复制代码
${\$aa}和$aa是完全不一样的
$aa是:
SV = PV(0x13df917 at 0x13cf7fc0
  REFCNT = 2
  FLAGS = (PADBUSY,PADTMP,POK,READONLY,pPOK)
  PV = 0x13d1b820 "2"\0
  CUR = 1
  LEN = 8
${\$aa}是:
SV = PV(0x13cf8160) at 0x13cf72a0
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x13df5b20 "2"\0
  CUR = 1
  LEN = 8
由于$aa是在for循环里的列表中一个常量值的引用,所以reference count已经是2了,而且已经被标记为READONLY,是不可写的。
但${\$aa}没有强制READONLY,所以可以赋值。但赋值是没起作用的,$aa永远不变。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP