代码之家  ›  专栏  ›  技术社区  ›  Ryan Fox

为什么要在Perl中导出符号?

  •  2
  • Ryan Fox  · 技术社区  · 15 年前

    A. very common problem 这是由于使用 CGI LWP::Simple 同时两个包裹都出口 head()

    5 回复  |  直到 15 年前
        1
  •  9
  •   user181548 user181548    15 年前

    默认情况下从模块导出所有函数的做法不是Perl推荐的做法。只有在有充分理由的情况下才能导出函数。建议的做法是使用 EXPORT_OK 因此,用户必须键入所需函数的名称,如:

    use My::Module 'my_function';
    

    以前的模块,如LWP::Simple和CGI,都是在本建议提出之前编写的,现在很难将它们修改为不导出东西,因为这会破坏现有的软件。我猜这个建议是通过人们注意到这样的问题而产生的。

    无论如何,Perl的面向对象对象或它的任何调用都不需要您导出任何东西,而且您不必说$foo->,所以你问题的那部分是错的。

        2
  •  9
  •   brian d foy    15 年前

    导出是一项功能。和任何语言中的其他特性一样,如果您(ab)过于频繁地使用它,或者在不应该使用它的地方,它可能会导致问题。明智地使用它是好的,反之则是坏的,就像其他任何功能一样。

    在没有太多模块的时候,默认情况下导出东西并不是件坏事。然而,CPAN上有15000个包,必然会有冲突,这是不幸的。但是,现在修复模块可能会破坏现有代码。每当你做出一个糟糕的界面选择并向公众发布它时,即使你不喜欢它,你也会致力于它。

        3
  •  6
  •   Chris Lutz    15 年前

    导出包不知道正在使用的包是否已经定义了同名的符号,当然也不能保证它是唯一导出同名符号的包。

    如果你想的话,我想你 import() 例程可以检查,但默认的Exporter.pm例程不检查(而且可能不应该检查,因为它将被大量使用,并且始终检查是否定义了名称将导致严重的减速(如果发现冲突,Exporter应该怎么做?)。

    在我看来,这样做的唯一原因是懒惰。通过不键入Foo::或使用对象接口,可以节省一些笔划,但这真的值得吗?

    Foo:: 不是很糟糕,但是考虑一下 My::Company::Private::Special::Namespace:: -如果我们只导出一些东西,您的代码将看起来更干净。并非所有内容都可以(或应该)位于顶级命名空间中。

    当导出机制使代码更干净时,应该使用它。当名称空间发生冲突时,不应该使用它,因为它显然不能使代码更干净,但除此之外,我非常喜欢在请求时导出东西。

        4
  •  3
  •   Ether    15 年前

    Moose Rose::DB::Object ,一个流行ORM的对象接口。两者都导入了 meta 方法进入 use

    实际上,这与从模块(每个模块都提供相同名称的方法)进行乘法继承的问题没有什么不同,只是父代的顺序将决定调用该方法的哪个版本(或者您可以定义自己的重写版本,以某种方式手动将父代和子代的功能折叠在一起)。

        5
  •  3
  •   Eric Strom    15 年前

    Perl的“开放”包的一个优点是,如果您对模块作者设计的方式不感兴趣,您可以更改它。

    package LWPS;
    require LWP::Simple;
    
    for my $sub (@LWP::Simple::EXPORT, @LWP::Simple::EXPORT_OK) {
        no strict 'refs';
        *$sub = sub {shift; goto &{'LWP::Simple::' . $sub}};
    }
    
    package main;
    
    my $page = LWPS->get('http://...');
    

    当然在这种情况下,, LWP::Simple::get()