免费注册 查看新帖 |

Chinaunix

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

Perl 语言深坑之模块互相调用 [复制链接]

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2017-09-12 20:28 |只看该作者 |倒序浏览
Perl 语言模块互相调用会出现问题。

如果 Package A 中需要 Package B 的一个函数,而 Pakcage B 也需要 Package A 的导出函数,那么总有一个无法调用。

对于这个问题,要么合并两个模块,要么解除两者之间的互相调用关系。

  1. $ cat call-eachother.pl
  2. #!perl

  3. {
  4.    package A;

  5.    use 5.012;

  6.    use Exporter;
  7.    our @ISA = qw(Exporter);
  8.    our @EXPORT = qw(a_call);

  9.    use B qw(b_call);

  10.    sub a_call {
  11.       say "this is a_call()";
  12.       b_call();
  13.    }

  14.    1;
  15. }

  16. {
  17.    package B;

  18.    use 5.012;

  19.    use Exporter;
  20.    our @ISA = qw(Exporter);
  21.    our @EXPORT = qw(b_call);

  22.    use A qw(a_call);

  23.    sub b_call {
  24.       say "this is b_call()";
  25.       a_call();
  26.    }

  27.    1;
  28. }

  29. A::a_call();
  30. B::b_call();


  31. ssqq@SZQ C:\Users\ssqq\Spp\lib
  32. $ perl call-eachother.pl
  33. "b_call" is not exported by the B module
  34. Can't continue after import errors at call-eachother.pl line 12.
  35. BEGIN failed--compilation aborted at call-eachother.pl line 12.
复制代码




论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
2 [报告]
发表于 2017-09-13 08:28 |只看该作者
再加个c或许就可以了

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
3 [报告]
发表于 2017-09-13 08:37 |只看该作者
直接用带包全名就可以了,加 C 也是循环引用,不知道可以不可以,这是欺骗编译器的行为

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
4 [报告]
发表于 2017-09-13 21:44 |只看该作者
本帖最后由 zhlong8 于 2017-09-13 21:46 编辑

你知道 Perl 自带个模块叫 B 吗?


假设你解决名字的问题那么

如果用户 use A; 按实际执行顺序是
编译A.pm ->
遇到 use B;语句 ->
编译B.pm ->
B 中遇到 use A; ->
此时A在编译,无需重复编译 ->
执行 A->import('a_call') ->
此时 @ISA='Exporter'; @EXPORT='a_call'; 还没开始执行,因为A编译都还没完成,怎么执行. 修改代码 use base 'Exporter'; BEGIN { @ EXPORT = 'a_call'; } 放在 A.pm 的 use B; 之前 ->
A中继承来 Exporter 的 import 方法,A->import('a_call') 可以正确执行,导入正确的符号 a_call 到 package B ->
B 编译完找到符号a_call(), 执行B.pm ->
A 中执行 B->import('b_call') 成功 ->
编译A中 use B 之后的代码 ->
A 编译完成,执行 A 模块代码 ->

客户 use A; 完成整个 A B 模块的导入。关键在于分清编译和执行两步顺序,use A qw(args); 等价于 BEGIN{ require A; A->import(qw(args)); }

论坛徽章:
0
5 [报告]
发表于 2017-09-14 00:12 |只看该作者
回复 4# zhlong8

版主正解。
话说现在use base ’Exporter‘;这个,现在很多人喜欢写use Exporter 'import';即不需要继承Exporter。

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
6 [报告]
发表于 2017-09-14 11:35 |只看该作者
版主说了很多,看不懂,不知道是说什么。也不清楚不能互相调用是用错了模块名称,还是编译器不允许。

修改了模块名称,模块之间是可以相互调用的。

  1. $ cat call-each.pl
  2. #!perl

  3. {
  4.    package AA;

  5.    use 5.012;

  6.    use Exporter;
  7.    our @ISA = qw(Exporter);
  8.    our @EXPORT = qw(a_call);

  9.    # use BB;

  10.    sub a_call {
  11.       say "this is a_call()";
  12.       BB::b_call();
  13.    }

  14.    1;
  15. }

  16. {
  17.    package BB;

  18.    use 5.012;

  19.    use Exporter;
  20.    our @ISA = qw(Exporter);
  21.    our @EXPORT = qw(b_call);

  22.    sub b_call {
  23.       say "this is b_call()";
  24.       AA::a_call();
  25.    }

  26.    1;
  27. }

  28. AA::a_call();
  29. BB::b_call();
复制代码


运行后,产生了循环调用,当然实际中是有退出条件的。
  1. this is b_call()
  2. this is a_call()
  3. this is b_call()
  4. this is a_call()
  5. this is b_call()
  6. this is a_call()
  7. this is b_call()
  8. this is a_call()
  9. this is b_call()
  10. this is a_call()
  11. this is b_call()
  12. this is a_call()
  13. this is b_call()
  14. this is a_call()
  15. this is b_call()
  16. this is a_call()
  17. this is b_call()
  18. this is a_call()
  19. Terminating on signal SIGINT(2)
复制代码

论坛徽章:
0
7 [报告]
发表于 2017-09-17 22:41 |只看该作者
104359176 发表于 2017-09-14 11:35
版主说了很多,看不懂,不知道是说什么。也不清楚不能互相调用是用错了模块名称,还是编译器不允许。

修 ...

Perl 有一个标准模块叫 B 。
你定义包B ,等于覆盖了Perl的标准模块。 所以换名称就可以了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP