免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 14950 | 回复: 11
打印 上一主题 下一主题

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

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-04 15:11 |显示全部楼层 |倒序浏览
我自认为这方面弄的挺明白的,没想今天出这么个问题。。。非想弄明白了这个foreach和shift操作上的差别。

当函数返回数组引用的时候foreach和shift操作起来是一样的:
  1. sub function {
  2.     my @temp = qw/a b c/;
  3.     return \@temp;
  4. }

  5. foreach my $var (@{&function}) {
  6.     print "$var\n";
  7. }

  8. my $one = shift (@{&function});
  9. print $one;
复制代码
当函数返回数组的时候shift就会出问题,提示:
Type of arg 1 to shift must be array (not subroutine entry)

代码:
  1. sub function {
  2.     my @temp = qw/a b c/;
  3.     return @temp;
  4. }

  5. foreach my $var (&function) {
  6.     print "$var\n";
  7. }

  8. my $one = shift (&function);
  9. print $one;
复制代码
从错误提示上看我需要做的应该是提示Perl传给shift的参数是一个数组。
我想了各种办法都没成功。。。

请大家给掌掌眼~~

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2010-08-04 21:09 |显示全部楼层
回复 4# dugu072_cu


谢谢。

我试了好多这样的写法都没写对,你写的是对的。这正是我和自己较劲想得到的答案。

这样写就强制将一个匿名列表转换成了一个real array。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2010-08-04 21:21 |显示全部楼层
回复 2# toniz


恩,对,函数返回的的确是参数列表,比如,函数可以返回两个参数,第一个参数是一个数组,第二个是一个哈希表。

那foreach怎么就能正确处理函数的返回值呢?函数的返回值如果是一个数组的时候和真实的数组有什么差别?


。。。。我再研究研究,总结一下。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2010-08-05 08:26 |显示全部楼层
说返回“列表”还是返回“数组”,这其实是一样的,但严格意义上说,我觉得应该说是返回了列表.
列表是数据,return @temp和return qw/a b c/无异。
文档中关于return部分也写到:“Evaluation of EXPR may be in list, scalar, or void context, depending on how the return value will be used”

shift实际是个函数,和map一样,在识别参数的时候都有局限性,我开始就是觉得是shift的问题,所以才想尽办法用类似“强制告诉shift我那function返回的是个数组”,其实我想要的就是这个写法“shift( @{ [ &func ] } )”
我本该想到的。。。以前对哈希表做过类似的事。

我再多说一句。@{ [ &function ] }的意思,里面的中括号就是强制数据为列表的形式,之后的大括号类似${abc},就是标识一下变量。前面再加上@也就真的成了一个数组了,这样shift函数就能认识了。
相应的,如果是强制数据以哈希表的形式出现,那就是%{ { &function } },这个我尝试过,是正确的。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2010-08-05 11:34 |显示全部楼层
#!/bin/env perl

use strict;
use warnings;

sub func_array
{
        my @temp = qw/a b ...
黑色阳光_cu 发表于 2010-08-05 08:58


这就是标量上下文和列表上下文的问题了。
我的理解是这样的,如果把一个list存起来,那就是一个array,比如@name = qw/a b c/中,qw/a b c/是list,@name就是array。
qw/a b c/是('a','b','c'),你用scalar(func_list())相当于scalar qw/a b c/,这个scalar是一元的,它会对a,b,c分别做scalar,然后在标量上下文中返回scalar(c)。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2010-08-05 11:35 |显示全部楼层
回复 10# flw


我把标题写成那样就是想让你来给我个"大背跨",呵呵。很多概念我还是模糊。。。你快给说说吧。。。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2010-08-05 13:01 |显示全部楼层
我错了。把Perl的上下文忘了。

但那个报错,确实是发生在编译时~~~~
黑色阳光_cu 发表于 2010-08-05 12:10



恩,对,只要打开-w选项,运行程序的时候是能看到提示的。

Type of arg 1 to shift must be array (not subroutine entry) at ./function.pl line 17, near "&function)"
Execution of ./function.pl aborted due to compilation errors.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2010-08-05 14:55 |显示全部楼层
ft~
有这么麻烦嘛,与什么上下文无关,就一点: list是 value,array 是 variable!
由于 shift 要修改传 ...
dugu072_cu 发表于 2010-08-05 14:40



说“上下文”的时候,说的是另一个问题,是在说scalar的输出结果为什么会不同。

你这个解释很有道理,呵呵。。。

之前我一直认为foreach的行为就相当于shift的行为,但显然不是。。。 shift就是pop,是要对数组进行修改的,foreach只是读而已。

试了下,shift (qw/a b c/)是会报错的,提示shift must be array (not list)

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 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,为什么就不算常量了...?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 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有例子在解释,我觉得说的也有道理。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP