Аргумент передан подпрограмме Perl VERSION во время проверки версии модуля - PullRequest
0 голосов
/ 27 сентября 2018

Я определяю модуль Perl следующим образом:

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

package Sample;
use Data::Dumper; 
our $VERSION = v1.10;

sub VERSION
{
    my ($class, $version) = @_;
    print ("version is $version\n");
    print Dumper ($version);
}

Характер значения, переданного в $version, изменяется в зависимости от того, как импортируется модуль:

$ perl -e 'use Sample 1.0'
version is 1
$VAR1 = '1';

Однако, если требуемая версия модуля указана в виде v-строки:

$ perl -e 'use Sample v1.0'
version is 
$VAR1 = v1.0;

Какой тип данных передается в $version во втором случае?Это, очевидно, не простой скаляр, и это не ссылка.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Каждое число, разделенное точкой, преобразуется в символ с порядковым значением числа. [1] Другими словами,

v1.0   ≡   "\x01\x00"   ≡   chr(1).chr(0)   ≡   pack('W*', 1, 0)

Вы можете преобразовать v-строкув нечто читаемое человеком, используя спецификатор формата %vd sprintf. [2]

$ perl -e'CORE::say sprintf("%vd", v1.0)'
1.0

Но лучше использовать модуль version .

$ perl -Mversion -e'CORE::say version->parse(v1.0)'
v1.0

Это лучше, потому что модуль версии может обрабатывать строки версии в целом (не только v-строки).

$ perl -Mversion -e'
   my $v1 = version->parse(1.0);
   my $v2 = version->parse("1.0");
   my $v3 = version->parse(v1.0);
   my $v4 = version->parse("v1.0");
   CORE::say "equal"
      if $v1 == $v2
      && $v1 == $v3
      && $v1 == $v4
'
equal

Можно использовать любой оператор сравнения чисел или строк [3] для сравнения объектов версий.


  1. Хотя это больше, чем это.К скаляру, содержащему v-строку, применена магия (типа V), поэтому можно определить, что это v-строка.

    $ perl -MDevel::Peek -e'Dump("\x01\x00"); Dump(v1.0);'
    SV = PV(0xbc9d70) at 0xbe7998
      REFCNT = 1
      FLAGS = (POK,IsCOW,READONLY,PROTECT,pPOK)
      PV = 0xbf1ed0 "\1\0"\0
      CUR = 2
      LEN = 10
      COW_REFCNT = 0
    SV = PVMG(0xc20480) at 0xbe7938
      REFCNT = 1
      FLAGS = (RMG,POK,IsCOW,READONLY,PROTECT,pPOK)
      IV = 0
      NV = 0
      PV = 0xbf0190 "\1\0"\0
      CUR = 2
      LEN = 10
      COW_REFCNT = 0
      MAGIC = 0xbf3a80
        MG_VIRTUAL = 0
        MG_TYPE = PERL_MAGIC_vstring(V)
        MG_LEN = 4
        MG_PTR = 0xbf1700 "v1.0"
    

    Эта магия применяется даже к любому скаляру, к которому относитсяv-строка копируется!

    $ perl -MDevel::Peek -e'my $v1 = v1.0; my $v2 = $v1; Dump($v2)'
    SV = PVMG(0x9dc500) at 0x9a3a00
      REFCNT = 1
      FLAGS = (RMG,POK,IsCOW,pPOK)
      IV = 0
      NV = 0
      PV = 0x9ac1b0 "\1\0"\0
      CUR = 2
      LEN = 10
      COW_REFCNT = 2
      MAGIC = 0x9b8090
        MG_VIRTUAL = 0
        MG_TYPE = PERL_MAGIC_vstring(V)
        MG_LEN = 4
        MG_PTR = 0x9adef0 "v1.0"
    

    Я полагаю, что модуль версии использует эту информацию.

  2. Этот спецификатор формата работает с любой строкой, поэтому его удобнопроверка скрытых или специальных символов при отладке.

    $ perl -e'CORE::say sprintf "%v02X", "abc\r\n"'
    61.62.63.0D.0A
    
  3. ==, <, >, <=, >=, <=>, eq, lt, gt, le, ge и cmp.

0 голосов
/ 27 сентября 2018

Строка v является строкой.Предполагается, что каждое число является кодовой точкой Unicode и преобразуется в этот символ, так что на самом деле вы печатаете chr (1).CHR (0).Вы можете доказать это с помощью следующего скрипта

my $vstring = v80.101.114.108
print $vstring, "\n";

Это напечатает Perl

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