2010-06-14 38 views
6

Đôi khi tôi cần một chức năng tiện ích hữu ích, như List::Util::max ở giữa chương trình lớn thực hiện rất nhiều nội dung. Vì vậy, nếu tôi làmNhập khẩu một cách thủ công các chức năng hữu ích trong một tập lệnh lớn

use List::Util 'max'; 

Ở đầu chương trình, tôi bị mắc kẹt với biểu tượng đó, làm ô nhiễm toàn bộ không gian tên của tôi, mặc dù tôi chỉ cần nó trong một chương trình con.

Vì vậy, tôi đã nghĩ đến việc cố gắng một mô hình khác nhau, thay vì:

use List::Util(); 

# a whole bunch of stuff later... 
sub blah { 
    List::Util->import('max'); 
    $blah = max @foobar; 
    ... 
} 

Có hai vấn đề với điều này, mặc dù. Đối với một, nó không tự động unimport ở cuối khối (drat.) Tôi sẽ phải hoàn tác mọi thứ với một unimport.

Vấn đề khác là các nguyên mẫu rõ ràng không được áp dụng chính xác, vì vậy tôi phải nói max(@foobar) thay vì phiên bản không có dấu ngoặc đơn đẹp hơn.

Có cách nào dễ dàng để nhập tạm thời các biểu tượng cho một khối, tự động khiến chúng biến mất ở cuối khối và cũng xử lý mẫu chính xác không?

Trả lời

1

Bạn có thể bản địa hoá một mục bảng biểu tượng:

use List::Util(); 

@y = qw(1 3 5 -9 4); 

sub max { # return maximum *absolute value* of list 
    my $max = abs(shift); 
    $max<abs($_) && ($max=$abs($_)) for @_; 
    return $max; 
} 

sub max2 { 
    local *max = *List::Util::max; 
    return max(@_); 
} 

print "My max:   ", max(@y), "\n"; # ==> 9 
print "List::Util::max ", max2(@y), "\n"; # ==> 5 
+3

Điều này sẽ giới thiệu các lỗi tinh tế nếu 'max' có một nguyên mẫu, vì hiệu ứng của nó được đốt cháy trong lúc biên dịch. Trong 'max2', nguyên mẫu từ' main :: max' được sử dụng, không phải là từ 'List :: Util :: max'. Một cách cẩn thận, bạn sẽ nhận được một cảnh báo về nguyên mẫu không phù hợp khi chuyển nhượng. –

+0

@Eric Strom - Điểm tốt, điều đó sẽ hút. Sử dụng tên chương trình con 'cục bộ 'một cách thận trọng. – mob

4

Chỉ cần làm điều này, nó tốt hơn nhiều và rõ ràng hơn:

package Foo; 
use strict; use warnings; 
use List::Util 'max'; 
use namespace::autoclean; 

# your method definitions here... 

namespace::autoclean sẽ "unimport" biểu tượng sau chu kỳ biên soạn của gói được thực hiện. Cuộc gọi đến phương thức của bạn sẽ vẫn hoạt động, nhưng bạn không có ô nhiễm không gian tên (biểu tượng *Foo::max bị xóa) và gọi $obj->max() sẽ không thành công.

Ngoài ra, bạn có thể muốn xem Lexical::Import (Tôi không biết gì về nó; một chú chim hồng ngoại đã đề cập đến nó).

+0

Trong khi 'không gian tên :: autoclean' là không đúng, nó không giải quyết được vấn đề chính là' max' vẫn còn trong toàn bộ gói thay vì giới hạn trong một khối duy nhất là những gì tôi thực sự đang cố gắng đạt được. Tôi muốn các hàm tiện ích của tôi hoạt động như các biến từ vựng. – friedo

+0

@friedo: tại sao nó là một vấn đề 'max' có sẵn cho toàn bộ gói? Nếu mối quan tâm là ô nhiễm không gian tên, đó là những gì mô-đun này sẽ chăm sóc. – Ether

+0

Có lẽ tôi muốn một * khác * 'max' ở một nơi khác trong gói. – friedo

1

perlfunc ngụ ý rằng no MODULE nên làm những gì bạn muốn:

sub blah { 
    use List::Util qw(max); 
    say max @foobar; 
    no List::Util; 
} 

nhưng điều đó không làm việc - ít nhất là không cho liệt kê: : Util. Tôi tin rằng nó sẽ cần phải xác định một phương pháp unimport. Thậm chí sau đó, tôi không chắc chắn nếu bạn có thể có một max trần trong mô-đun của bạn gọi định nghĩa khác nhau.

+0

Các dòng 'use' và' no' có thực thi tại một thời điểm khác (sớm hơn) so với phần còn lại của định nghĩa phụ không? – Ether

+0

Cả 'use' và' no' đều xảy ra tại thời gian biên dịch; chúng sẽ bị xử tử trong khi 'blah' được biên dịch. –

2

Nếu bạn chỉ sử dụng tối đa trong một chương trình con, tôi sẽ không nhập nó vào không gian tên nào cả. Giải pháp của tôi là

use List::Util; 
sub blah { 
    print List::Util::max(@list); 
} 
+0

Điều này vẫn tôn vinh nguyên mẫu, vì vậy bạn có thể bỏ dấu ngoặc đơn: danh sách in :: Util :: max @list; – dwarring

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