免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-09-20 15:30 |只看该作者 |倒序浏览
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;



[ 本帖最后由 cobrawgl 于 2007-9-20 17:13 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-09-20 17:01 |只看该作者
不知道类似的程序在 ruby和 python 里是什么输出?

谁给试一试?

论坛徽章:
0
3 [报告]
发表于 2007-09-21 09:24 |只看该作者
你的程序中的f里面的$x没有被初始化,所以是0。如下就正常了:
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块在程序其他部分之前执行,可以保证使用子程序之前就初始化了"静态"变量。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2007-09-21 09:46 |只看该作者
我昨天到 maillist 问了一下,
据说是一个已知的 bug,
我翻了翻 bugs.perl.org,没找到。
有兴趣的可以找一下。

论坛徽章:
0
5 [报告]
发表于 2007-09-21 09:52 |只看该作者
这里好有意思啊,今天在perl下测试,是这个结果
0A,1B,2C,3D,
这里闭包的使用,感觉像$F和$G引用了不同的块
而且。。为什么一个是数字,一个是字母
往高手赐教

论坛徽章:
0
6 [报告]
发表于 2007-09-21 11:02 |只看该作者
有人说这是perl5在实现closure上的一个小bug

等高手出来解惑

论坛徽章:
0
7 [报告]
发表于 2007-09-21 11:08 |只看该作者
为什么我的结果是:
AB,CD,EF,GH,
没有1,2,3,等数字

论坛徽章:
0
8 [报告]
发表于 2007-09-21 11:23 |只看该作者
原帖由 ouyangyu139 于 2007-9-21 11:08 发表
为什么我的结果是:
AB,CD,EF,GH,
没有1,2,3,等数字

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

感觉closure越看越危险啊。。。

论坛徽章:
0
9 [报告]
发表于 2007-09-21 13:58 |只看该作者
楼上的,不好意思.
我copy的三楼的.


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

不过我很不解.
能不能详细解释一下此程序.
谢谢!

论坛徽章:
0
10 [报告]
发表于 2007-09-21 14:10 |只看该作者
这可能是perl的一个小bug,但是也可以看做不是。

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

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

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.不提及变量,结果为未初始化
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。提及变量,结果正常。
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,

[ 本帖最后由 royalzhang 于 2007-9-21 14:57 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP