Chinaunix

标题: foreach中调用函数的奇怪现象 [打印本页]

作者: nhw_cs    时间: 2010-11-11 11:27
标题: foreach中调用函数的奇怪现象
废话少说, 请看:

test1.pl:
------------------
#!/usr/bin/perl -w

my $var1="dd";
my @var2=("aa", "bb", "cc";
while( $var1=shift(@var2)) {
&func;
}

sub func {
print "Value of var1var1\n";
}
--------------------
执行结果:
Value of var1:aa
Value of var1:bb
Value of var1:cc

test2.pl
-------------------------------
#!/usr/bin/perl -w

my $var1="dd";
my @var2=("aa", "bb", "cc";
foreach $var1 (@var2) {
&func;
}

sub func {
print "Value of var1var1\n";
}
----------------------

执行结果:
Value of var1:dd
Value of var1:dd
Value of var1:dd

两段代码看上去逻辑上应该等价, 为什么结果不同?
作者: iamlimeng    时间: 2010-11-11 11:38
变量作用域的问题。
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. my $var1="dd";
  5. my @var2=("aa", "bb", "cc");
  6. foreach $var1 (@var2) {
  7.         print "$var1\n";
  8.         &func;
  9. }

  10. sub func {
  11.         print "Value of var1 $var1\n";
  12. }
复制代码

作者: nhw_cs    时间: 2010-11-11 11:42
回复 2# iamlimeng


  我知道是变量作用域问题, 但为什么foreach怎么这么特殊? 怎么就和while不同了? 求甚解 ....
作者: zhlong8    时间: 2010-11-11 12:11
回复 1# nhw_cs


    perlsyn
The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn. If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop. This implicit localisation occurs only in a foreach loop.

作者: gaochong    时间: 2010-11-11 12:48
回复 3# nhw_cs


    控制变量,建议加my
作者: happig    时间: 2010-11-11 14:00
回复  nhw_cs


    perlsyn
zhlong8 发表于 2010-11-11 12:11



    先翻配套手册这种习惯是解决问题的有效途径!
作者: alabos    时间: 2010-11-11 14:21
foreach 隐式的声明了  my $var1 它做为一个自己的私有变量用了。



作者: nhw_cs    时间: 2010-11-11 14:34
foreach 隐式的声明了  my $var1 它做为一个自己的私有变量用了。
alabos 发表于 2010-11-11 14:21



    上面的英文解释已经说明这个问题了。 到这里对很多人来说问题就结束了, 但我仍认为这不能算是完全的"求甚解". 因为我想肯定很多人都觉得perl这样规定很奇怪, 当然人家这样做肯定有他的原因, 那我们就再进一步问: Perl为什么要这样做? 弄清这个才算到底。而不是仅仅记住这样一个规定.

我其实好像已经知道为什么了, 但我现在还不说 .....
作者: nhw_cs    时间: 2010-11-11 14:37
回复  nhw_cs


    控制变量,建议加my
gaochong 发表于 2010-11-11 12:48



   
作为一个05年注册的非新人, 这么唐突的回答令我愕然. 我虽然不是perl高手, 但深谙编程语言的内在本质, 如果是my这样简单的问题, 我会拿来问么? 高手的问题肯定没那么简单 ....
作者: zhlong8    时间: 2010-11-11 14:55
难道楼主所说的深意是指 VAR 其实只是别名,所以这样设计?
作者: toniz    时间: 2010-11-11 15:09

作者: toniz    时间: 2010-11-11 15:17
foreach出来的就是别名,可以通过它改变数组内容滴。
作者: toniz    时间: 2010-11-11 15:19
貌似之前和其它人在这个版讨论过这问题,不过刚没翻到。。
作者: toniz    时间: 2010-11-11 15:39
本帖最后由 toniz 于 2010-11-11 15:50 编辑

下面这个代码可以说明部分问题。
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my $var1="dd";

  5. {
  6.         our $var1='cc';
  7.         print "$var1 \n";
  8.         &func;
  9. }

  10. sub func {
  11.         print "Value of $var1\n";
  12. }
复制代码
结果为:
cc
Value of dd


别名可以看成使用符号表的变量。而MY定义的变量是词法范围的。而你的代码func并没有传递参数,考虑到作用域,所以这里函数取到的就是MY的值。

如果用下面的代码:
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my $var1="dd";


  5.         our $var1='cc';
  6.         print "$var1 \n";
  7.         &func;


  8. sub func {
  9.         print "Value of $var1\n";
  10. }
复制代码
结果为:
cc
Value of cc

这时候就是使用符号表的变量。

所以这类代码为了避免混乱,最好是使用函数参数来传递值。
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my $var1="dd";

  5. {
  6.         our $var1='cc';
  7.         print "$var1 \n";
  8.         &func($var1);
  9. }

  10. sub func {
  11.         my $var2=shift;
  12.         print "Value of $var2\n";
  13. }
复制代码

作者: nhw_cs    时间: 2010-11-11 16:29
难道楼主所说的深意是指 VAR 其实只是别名,所以这样设计?
zhlong8 发表于 2010-11-11 14:55



    正解! 但此意不深 结贴!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2