2010-06-04 29 views
6

Từ tất cả những gì tôi đã đọc về việc sử dụng các module Perl, việc sử dụng cơ bản là:Perl - Gói vấn đề/Module

  • tập tin Module với .pm mở rộng, bao gồm báo cáo kết quả package <name>, nơi <name> là tên file của mà không có phần mở rộng.
  • Tệp mã sử dụng mô-đun có chứa câu lệnh use <name>;.

Ứng dụng tôi đang mã hóa có một tập lệnh mã chính sử dụng khoảng 5 mô-đun. Tôi đã quên bao gồm tuyên bố package <name> trong các mô-đun, nhưng mã của tôi vẫn chạy tốt với tuyên bố use <name>. Tôi bắt đầu nhận được lỗi Undefined subroutine với một trong các mô-đun, vì vậy tôi đã thêm tuyên bố gói vào từng mô-đun. Bây giờ phần còn lại của các mô-đun đó ngừng hoạt động. Đưa cái gì?

Ví dụ:

mainapp.pl

#!/usr/bin/perl 
use UtyDate; 
my $rowDate = CurrentDate("YYYYMMDD"); 

UtyDate.pm

#!/usr/bin/perl 
package UtyDate; 
sub CurrentDate 
{ 
    #logic 
} 
return 1; 

Khi tôi chạy mã trên, tôi nhận được lỗi Undefined subroutine &main::CurrentDate called at.... Tuy nhiên, nếu tôi xóa dòng package UtyDate; khỏi UtyDate.pm, tôi sẽ không gặp lỗi. Tình trạng này tồn tại đối với một số nhưng không phải tất cả các mô-đun của tôi.

Rõ ràng là có nhiều mã hơn tôi không hiển thị, nhưng tôi nhầm lẫn cách bất kỳ mã nào tôi không hiển thị có thể ảnh hưởng đến cấu trúc gói/sử dụng mà tôi đã hiển thị ở đây.

Trả lời

10

Khi bạn sử dụng một mô-đun, mã trong các mô-đun được chạy ở thời gian biên dịch. Sau đó, nhập khẩu được gọi là tên gói cho module. Vì vậy, use Foo; giống với BEGIN { require Foo; Foo->import; }

Mã của bạn đã làm việc mà không có tờ khai main, được sử dụng bởi mã ứng dụng chính.

Khi bạn thêm các khai báo package nó ngừng hoạt động, vì các chương trình con bạn đã xác định không còn được xác định trong main, nhưng trong UtyDate.

Bạn có thể truy cập các chương trình con bằng cách sử dụng tên đủ điều kiện UtyDate::CurrentDate(); hoặc bằng cách nhập các chương trình con vào không gian tên hiện tại khi bạn use mô-đun.

UtyDate.pm

package UtyDate; 
use strict; 
use warnings; 

use Exporter 'import'; 

# Export these symbols by default. Should be empty!  
our @EXPORT =(); 

# List of symbols to export. Put whatever you want available here. 
our @EXPORT_OK = qw(CurrentDate AnotherSub ThisOneToo); 

sub CurrentDate { 
    return 'blah'; 
} 

sub AnotherSub { return 'foo'; } 

chương trình chính:

#!/usr/bin/perl 
use strict; 
use warnings; 

use UtyDate 'CurrentDate'; 

# CurrentDate is imported and usable.  
print CurrentDate(), " CurrentDate worked\n"; 

# AnotherSub is not 
eval { AnotherSub() } or print "AnotherSub didn't work: [email protected]\n"; 

# But you can still access it by its fully qualified name 
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n"; 

Xem Exporter tài liệu cho biết thêm.

+2

OP nên đọc ' perlmod' (http://search.cpan.org/perldoc/perlmod) trước tiên là điều kiện tiên quyết để hiểu những gì xảy ra trong 'Trình xuất'. – mob

+0

Giải thích tuyệt vời, cảm ơn. Tôi đã thấy Nhà xuất khẩu được sử dụng trong một số ví dụ mà tôi đã thấy, nhưng không phải tất cả, vì vậy tôi nghĩ rằng nó không liên quan. Tôi sẽ xem xét tài liệu quá đông đảo, cảm ơn. – brydgesk

3

Bạn thiếu mã tiêu đề perl của nhà xuất khẩu. Bạn sẽ cần phải thêm một cái gì đó như sau để phía trên cùng của tập tin pm của bạn dưới đây tuyên bố gói:

package UtyDate; 
BEGIN { 
    use Exporter(); 
    use vars qw($VERSION @ISA @EXPORT); 
    $VERSION = "1.0.0"; 
    @ISA = qw(Exporter); 
    @EXPORT = qw(&CurrentDate); 
} 

Xem liên kết này: http://perldoc.perl.org/Exporter.html#DESCRIPTION

+0

Chỉnh sửa theo http://p3rl.org/Exporter#Good_Practices hoặc sử dụng tốt hơn [Sub :: Exporter] (http://p3rl.org/Sub::Exporter) ngay từ đầu. – daxim

1

Ngoài ra để gợi ý Gray, bạn có thể làm điều này:

0

Ngoài việc sử dụng nhà xuất khẩu, như Gray chỉ ra, bạn có thể (UGLY, nhưng hoạt động) cũng gọi các chức năng có tên mô-đun.

Bạn fu nctiond/thủ tục không làm việc kể từ bây giờ họ đang ở trong một không gian tên differen (được xác định bởi tên mô-đun)

use UtyDate; 

UtyDate::CurrentDate() 
+1

Điều đó không xấu; đó là cách tiêu chuẩn để gọi các hàm không được viết theo kiểu OO. – Ether

+0

Không gian tên được xác định bởi cuộc gọi 'gói', không phải tên của mô-đun. Nó chỉ là một quy ước (mặc dù một cái tốt) rằng tên gói và tên mô-đun là như nhau. – mob

+0

@Ether: là tiêu chuẩn không giống như 'không xấu', tôi lo sợ. Bên cạnh đó, tôi có nghĩa là 'xấu xí' so với 'giải pháp' của Gray, đòi hỏi ít thay đổi hơn đối với mã đã được viết ('thay đổi nhiều' là những gì tôi cho là 'xấu' như trong: thay đổi lỗi khởi đầu. YMMV – lexu

Các vấn đề liên quan