大家对这个程序怎么看?谁能帮忙用 ruby、python 实现一下,看看结果?

大家对这个程序怎么看?谁能帮忙用 ruby、python 实现一下,看看结果?

use strict;
use warnings;

{
  my $x = 'A';
  sub f { sub { $x++ }       }
  sub g { sub { $x++ } if $x }
}
my $F=f();
my $G=g();
print $F->(),$G->(),"," for 1..4;



不知道类似的程序在 ruby和 python 里是什么输出?

谁给试一试?
你的程序中的f里面的$x没有被初始化,所以是0。如下就正常了:

QUOTE:
use strict;
use warnings;
BEGIN
{
  my $x = 'A';
  sub f { sub { $x++ }       }
  sub g { sub { $x++ } if $x }
}
my $F=f();
my $G=g();
print $F->(),$G->(),"," for 1..4;

BEGIN块在程序其他部分之前执行,可以保证使用子程序之前就初始化了"静态"变量。
我昨天到 maillist 问了一下,
据说是一个已知的 bug,
我翻了翻 bugs.perl.org,没找到。
有兴趣的可以找一下。
这里好有意思啊,今天在perl下测试,是这个结果
0A,1B,2C,3D,
这里闭包的使用,感觉像$F和$G引用了不同的块
而且。。为什么一个是数字,一个是字母
往高手赐教
有人说这是perl5在实现closure上的一个小bug

等高手出来解惑
为什么我的结果是:
AB,CD,EF,GH,
没有1,2,3,等数字


QUOTE:
原帖由 ouyangyu139 于 2007-9-21 11:08 发表
为什么我的结果是:
AB,CD,EF,GH,
没有1,2,3,等数字

你确定是copy一楼的程序吗?如果这样还真就麻烦了
还有,可以直接调用f->(),不需要申明F
当然,我这里的结果和用F是一样的

感觉closure越看越危险啊。。。
楼上的,不好意思.
我copy的三楼的.


我把一楼的也运行了一下,
这次的结果是:0A,1B,2C,3D,

不过我很不解.
能不能详细解释一下此程序.
谢谢!
这可能是perl的一个小bug,但是也可以看做不是。

普通的sub在运行前只编译一次,而匿名sub的每次调用都会重新编译。后者在作为closure使用的时候,应该在每次调用的时候取所在环境中的变量的值——类似于静态变量。

但从这个程序看来,运行阶段,f中的closure只取了所在sub的“可见”的变量,对于f可见的$x没有保留。也就是说,虽然f可以看见$x,但是由于在f中并没有提到$x,所以里面的closure在运行的时候就成了没有初始化的$x.  这在编译中通过了,不会报错,但是在运行中就出现了未预料的结果。
解决方法1,可以像3楼提到的,在{}前增加BEGIN,确保在加载阶段就正确初始化;
解决方法2,在f中“提及”一下闭包使用的变量,如下代码就可得到预期的结果:

QUOTE:
use strict;
use warnings;
{
  my $x = 'A';
  sub f {
         my $y = $x;  #提一下$x,让closure看到。$y is useless。
         sub { $x++ }     
        }
  sub g { sub { $x++ } if $x }
}
my $F=f();
my $G=g();
print $F->(),$G->(),"," for 1..4;

其实,g和f的区别,就是g里面提到了$x,而在f中是隐含看到$x的。

实验验证:
1.不提及变量,结果为未初始化

QUOTE:
use strict;
use warnings;
{
  my $x = 'A';   #给 g 所用
  my $y = '5';   #给 f 所用
  sub f {
        sub {  
         print "<",$y++,">";  #第一次运行时,closure看不见$y,只能取0初始化;         
                 $y                             # 返回值为$y+1                     
               }     
        }

  sub g { sub { $x++ } if $x }
}
my $F=f();
my $G=g();
print $F->(),$G->(),"," for 1..4; #打印结果:<0>1A,<1>2B,<2>3C,<3>4D,

2。提及变量,结果正常。

QUOTE:
use strict;
use warnings;
{
  my $x = 'A';
        my $y = '5';
  sub f {
             my $z = $y;  #提一下$y,让closure看到。
         sub {  
                 print "<",$y++,">";
                $y
                                 }     
        }
  sub g { sub { $x++ } if $x }
}
my $F=f();
my $G=g();
print $F->(),$G->(),"," for 1..4;  # 打印: <5>6A,<6>7B,<7>8C,<8>9D,