Можете ли вы заставить скаляр или ссылку на массив быть массивом в Perl?

У меня есть переменная perl, $resultsкоторая возвращается из службы. Значение должно быть массивом и $resultsдолжно быть ссылкой на массив. Однако если в массиве содержится только один элемент, ему $resultsбудет присвоено это значение, а не ссылочный массив, содержащий этот один элемент.

Я хочу сделать foreachцикл на ожидаемый массив. Без проверки ref($results) eq 'ARRAY', есть ли способ получить что-то эквивалентное следующему:

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

Этот конкретный пример кода будет работать для справки, но будет жаловаться на простой скаляр.

РЕДАКТИРОВАТЬ: Я должен уточнить, что я не могу изменить то, что возвращается от службы. Проблема состоит в том, что значение будет скалярным, когда есть только одно значение, и оно будет ссылкой на массив, если существует более одного значения.

6.08.2008 05:56:00
Такое поведение заставляет меня хотеть кричать и быть, как, "Глупый Перл!" Но потом я понимаю, что языки, которые не требуют этой чепухи, все еще делают это под капотом, что делает меня менее беспокойным ...
Rooster 10.03.2017 22:50:23
6 ОТВЕТОВ
РЕШЕНИЕ

я не уверен, что есть другой способ, кроме:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
26
6.08.2008 07:13:16

Я только что проверил это с:

#!/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";
}

И, кажется, работает нормально, так что я думаю, что это как-то связано с возвращением результата из службы? Если у вас нет контроля над службой возврата, это может быть трудно взломать

0
12.10.2008 12:29:45

Я бы перефакторинг кода внутри цикла, а затем сделать

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

Конечно, я сделал бы это, только если код в цикле был нетривиальным.

0
14.08.2008 21:45:53

Другим решением было бы обернуть вызов к серверу и заставить его всегда возвращать массив, чтобы упростить остаток вашей жизни:

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

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

Тогда вы всегда можете знать, что вернете ссылку на массив, даже если это был только один элемент.

foreach my $item (@{call_to_service()})
{
  ...
}
12
19.08.2008 14:16:57

Ну, если вы не можете сделать ...

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

или это...

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

тогда вам, возможно, придется попробовать что-то пугающе волосатое, как это! ....

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

и, чтобы избежать этой опасной строки, она становится ужасно уродливой !! ....

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

PS. Я предпочел бы абстрагировать его в примере под названием call_to_service (), представленном reatmon.

2
21.04.2017 15:03:26
Это не строка Eval. И зацикливание (некоторое выражение, включающее @ $ results) сильно отличается от зацикливания (@ $ results). Первый будет копировать массив (потребляя память); последний будет псевдонимом к нему (и позволит изменять элементы через переменную цикла).
ysth 1.12.2008 03:06:27
@ysth - есть ... см. "eval $ results". Мое предложение состояло в том, чтобы использовать приведенный выше пример call_to_service (). Мой ответ был чем-то вроде «языка в щеке» на ограничение, наложенное плакатом, так что да, это хорошо, чтобы указать на его недостатки.
draegtun 1.12.2008 14:41:01

Вы можете сделать это так:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
0
10.04.2017 09:37:20
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код. Также постарайтесь не переполнять ваш код пояснительными комментариями, это снижает удобочитаемость кода и пояснений!
kayess 23.11.2016 11:03:35