2008-08-06 31 views
24

Tôi có biến số perl $results được trả về từ dịch vụ. Giá trị được coi là một mảng và $results phải là tham chiếu mảng. Tuy nhiên, khi mảng chỉ có một mục trong đó, thì $results sẽ được đặt thành giá trị đó và không phải là mảng được tham chiếu có chứa một mục đó.Bạn có thể buộc tham số vô hướng hoặc mảng là một mảng trong Perl không?

Tôi muốn thực hiện vòng lặp foreach trên mảng dự kiến. Mà không kiểm tra ref($results) eq 'ARRAY', là có cách nào để có một cái gì đó tương đương như sau:

foreach my $result (@$results) { 
    # Process $result 
} 

Đó Đặc biệt mẫu mã sẽ làm việc cho các tài liệu tham khảo, nhưng sẽ phàn nàn về vô hướng đơn giản.

EDIT: Tôi nên làm rõ rằng không có cách nào để tôi thay đổi những gì được trả về từ dịch vụ. Vấn đề là giá trị sẽ là vô hướng khi chỉ có một giá trị và nó sẽ là một tham chiếu mảng khi có nhiều hơn một giá trị.

+0

Hành vi này khiến tôi muốn hét lên và được như thế, "PERL STUPID!" Nhưng sau đó tôi nhận ra rằng các ngôn ngữ không yêu cầu điều này vô nghĩa vẫn đang làm nó dưới mui xe, mà làm cho nó làm phiền tôi ít nhẹ hơn .... – Rooster

Trả lời

26

im không chắc chắn có bất kỳ cách nào khác hơn:

$result = [ $result ] if ref($result) ne 'ARRAY'; 
foreach ..... 
0

Tôi vừa thử nghiệm này với:

#!/usr/bin/perl -w 
use strict; 

sub testit { 

my @ret =(); 
if (shift){ 
    push @ret,1; 
    push @ret,2; 
    push @ret,3; 
}else{ 
    push @ret,"oneonly"; 
} 

return \@ret; 
} 

foreach my $r (@{testit(1)}){ 
    print $r." test1\n"; 
} 
foreach my $r (@{testit()}){ 
    print $r." test2\n"; 
} 

Và nó dường như làm việc ok, vì vậy tôi nghĩ nó có cái gì để làm với kết quả bị trở về từ dịch vụ? Nếu bạn không có quyền kiểm soát các dịch vụ trở về này có thể là khó ai để crack

0

tôi sẽ tái yếu tố mã bên trong vòng lặp và sau đó thực hiện

if(ref $results eq 'ARRAY'){ 
    my_sub($result) for my $result (@$results); 
}else{ 
    my_sub($results); 
} 

Tất nhiên tôi chỉ làm điều đó nếu mã trong vòng lặp không nhỏ.

12

Một giải pháp khác sẽ được quấn cuộc gọi đến máy chủ và có nó luôn trả về một mảng để đơn giản hóa phần còn lại của cuộc sống của bạn:

sub call_to_service 
{ 
    my $returnValue = service::call(); 

    if (ref($returnValue) eq "ARRAY") 
    { 
     return($returnValue); 
    } 
    else 
    { 
     return([$returnValue]); 
    } 
} 

Sau đó, bạn luôn có thể biết rằng bạn sẽ liên lạc lại một tham chiếu đến một mảng, ngay cả khi nó chỉ là một mục.

foreach my $item (@{call_to_service()}) 
{ 
    ... 
} 
2

Vâng, nếu bạn không thể làm ...

for my $result (ref $results eq 'ARRAY' ? @$results : $results) { 
    # Process result 
} 

hay này ...

for my $result (! ref $results ? $results : @$results) { 
    # Process result 
} 

sau đó bạn có thể phải thử một cái gì đó đáng sợ lông như thế này! .. ..

for my $result (eval { @$results }, eval $results) { 
    # Process result 
} 

và để tránh chuỗi nguy hiểm đó, nó trở thành thực sự xấu xí fugly !! ....

for my $result (eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] }) { 
    # Process result 
} 

PS. Sở thích của tôi là trừu tượng hóa nó trong ví dụ suba call_to_service() được đưa ra bởi reatmon.

+0

Đó không phải là một chuỗi eval. Và lặp lại (một số biểu thức liên quan đến @ $ kết quả) là rất khác nhau từ looping hơn (@ $ kết quả). Trước đây sẽ sao chép mảng (tiêu thụ bộ nhớ); sau này sẽ bí danh cho nó (và cho phép sửa đổi các phần tử thông qua biến vòng lặp). – ysth

+0

@ysth - Có ... xem "eval $ results". Đề xuất của tôi là sử dụng ví dụ call_to_service() được đưa ra trước đó. Câu trả lời của tôi là một chút của một "lưỡi trong giải pháp má" để hạn chế áp đặt bởi các poster vì vậy có tốt của nó để chỉ ra sai sót của nó. – draegtun

0

Bạn có thể làm điều đó như thế này:

my @some_array 
push (@some_array, results); 
foreach my $elt(@some_array){ 
    #do something 
} 
+0

Mặc dù đoạn mã này có thể giải quyết được câu hỏi, [bao gồm cả giải thích] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Ngoài ra, vui lòng không cố gắng gắn mã của bạn với các nhận xét giải thích, điều này làm giảm khả năng đọc của cả mã và giải thích! – kayess

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