Как можно хранить и использовать имена переменных и подпрограмм в Perl ha sh? - PullRequest
2 голосов
/ 20 июня 2020

Моя программа обрабатывает две разновидности «чего-то», и каждая разновидность имеет свои собственные структуры данных и процедуры для их обработки. Пользователь вызывает программу с одним или обоими из:

  • -f1 path_to_file_with_flavor_1_data
  • -f2 path_to_file_with_flavor_2_data

Моя программа работает с кодом:

GetOptions ('f1=s' => \$f1_path,
            'f2=s' => \$f2_path,
           );

if (defined $f1_path) {
  subroutine_to_process_flavor_1_data( $f1_path );
}
if (defined $f2_path) {
  subroutine_to_process_flavor_2_data( $f2_path );
}

Он имеет один ha sh для хранения обработанных данных для обоих ароматов:

my %flv_hash = ( flavor_1 => { datahash => { ... },
                             },
                 flavor_2 => { datahash => { ... },
                             },
               );

Теперь я хочу добавить имена переменных и подпрограмм каждого аромата в ha sh в сделайте это:

my %flv_hash = ( flavor_1 => { datahash => { ... },
                               var_name => 'f1_path',
                               sub_name => 'subroutine_to_process_flavor_1_data',
                              },
                 flavor_2 => { datahash => { ... },
                               var_name => 'f2_path',
                               sub_name => 'subroutine_to_process_flavor_2_data',
                              },
               );

и измените мою программу на псевдокод ниже:

foreach my $flavor ( keys %flv_hash ) {
   if (defined <the variable named $flv_hash{flavor}{var_name}>) {
      <call the subroutine named $flv_hash{flavor}{sub_name}>
   }
}

Я просмотрел все базы знаний на предмет хранения и извлечения имен переменных и подпрограмм в ha sh, но, будучи инженером по аппаратному обеспечению, чьи навыки программирования ограничены тем, что я изучил в Basi c Programming 101, что мне потребовалось около 35 лет go, я не мог напрямую скопировать примеры и получить их работать в рамках моей программы. Другими словами, если возможно, я был бы признателен за решение, которое я могу просто скопировать и использовать, не имея глубоких знаний о парадигмах Perl, на которых они основаны. Еще раз спасибо.

1 Ответ

6 голосов
/ 20 июня 2020

Единственное, что отсутствует в этом красивом макете, - это использование имен для подпрограммы и для переменной при формировании ha sh - вы не можете использовать эти вещи. затем, чтобы запустить подпрограмму или оценить переменную, используя только их простые имена.

Вместо этого вы можете взять ссылку на подпрограмму , которая является скаляром и, таким образом, может быть ha sh значение, после чего подпрограмма может быть выполнена путем разыменования его; и используйте переменную в качестве значения.

The ha sh

my %flv_hash = ( 
    flavor_1 => { 
        data => { ... },
        var  => $f1_path,
        code => \&subroutine_to_process_flavor_1_data,
    },
    flavor_2 => { 
        data => { ... },
        var  => $f2_path,
        code => \&subroutine_to_process_flavor_2_data,
    },
);

(это code для ключа - всего лишь заполнитель для лучшего имени). Чтобы использовать это, как указано,

foreach my $flavor ( keys %flv_hash ) {
   if (defined $flv_hash{$flavor}{var}) {
      $flv_hash{$flavor}{code}->( $flv_hash{$flavor}{var} );
   }
}

Синтаксис \&sub_name принимает и возвращает ссылку на подпрограмму , а также скаляр, который может быть назначен и / или обработан как любой другой скаляр.

Другой способ создания такой ссылки на код - использовать анонимную подпрограмму , напрямую назначая код подпрограммы с использованием синтаксиса

my $code_reference = sub { subroutine-code };

что вы также могли бы сделать в своем ha sh (code => sub { ... }), если бы подпрограммы были короткими и удобными.

Тогда обозначение $coderef->( LIST ) - это то, как мы выполняем подпрограмму со ссылкой на ее скаляр переменная $coderef. Если аргументов нет, нам нужны пустые скобки.

Конечно, есть несколько способов организовать это, если вы примете ссылки на код; Я просто следую разумному намерению из вопроса. Еще один элемент, который может быть полезен в этом ключе, - это таблица отправки ; одна недавняя ссылка находится на этой странице и многих других.

См. также, например, этот пост и многое другое эту статью из Эффективный перлер ... и c.

Мне пришло в голову, что, возможно, могут понадобиться и сами под-имена.

Простой способ получить имя из ссылки на код - использовать Sub :: Util

use Sub::Util qw(subname);

say subname( $coderef );

Это в ядре, так как, я думаю, perl -5.22.0 (?). Также есть Sub :: Identify на CPAN.

Затем всемогущий B дает это и многое другое через svref_2oject($coderef), что для ссылки на код возвращает B :: CV объект, на котором также могут использоваться методы B :: GV

use B qw(svref_2object);

my $cv = svref_2oject($coderef);

say for $cv->FILE, $cv->GV->NAME;  # etc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...