Как я говорю, какое значение находится в переменной Perl?

Вот пример:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

int main() {
    const char* const list[] = {"zip", "zam", "bam"};
    const size_t len = sizeof(list) / sizeof(list[0]);

    for (size_t i = 0; i < len; ++i)
        std::cout << list[i] << "\n";

    const std::vector<string> v(list, list + len);
    std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}
57
задан brian d foy 13 November 2009 в 20:32
поделиться

5 ответов

ref () :

Perl предоставляет функцию ref () , чтобы вы могли проверить тип ссылки перед разыменованием ссылки ...

Используя функцию ref () , вы можете защитить программный код, разыменовывающий переменные, от ошибок при использовании неправильного типа ссылки ...

53
ответ дан 24 November 2019 в 19:30
поделиться

Скаляр всегда выполняется единый элемент. Все, что находится в скалярной переменной, всегда является скаляром. Ссылка - это скалярное значение.

Если вы хотите узнать, является ли это ссылкой, вы можете использовать ref . Если вы хотите узнать тип ссылки, Ссылка - это скалярное значение.

Если вы хотите узнать, является ли это ссылкой, вы можете использовать ref . Если вы хотите узнать тип ссылки, Ссылка - это скалярное значение.

Если вы хотите узнать, является ли это ссылкой, вы можете использовать ref . Если вы хотите узнать тип ссылки, вы можете использовать подпрограмму reftype из Scalar :: Util .

Если вы хотите узнать, является ли это объект, вы можете использовать подпрограмму blessed из Scalar :: Util . Однако вам никогда не следует заботиться о том, что такое благословенный пакет. UNIVERSAL имеет несколько методов, чтобы сообщить вам об объекте: если вы хотите проверить, есть ли у него метод, который вы хотите вызвать, используйте can ; если вы хотите увидеть, что он наследуется от чего-то, используйте isa ; и если вы хотите увидеть, что объект выполняет роль, используйте DOES .

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

Если вы хотите узнать, похож ли он на число, вы можете использовать look_like_number из Scalar :: Util . Если оно не похоже на число и не является ссылкой, то это строка. Однако все простые значения могут быть строками.

Если вам нужно сделать что-то более интересное, вы можете использовать такой модуль, как Params :: Validate .

18
ответ дан 24 November 2019 в 19:30
поделиться

$ x всегда является скаляром. Подсказка - это сигил $ : любая переменная (или разыменование какого-либо другого типа), начинающаяся с $ , является скаляром. (Подробнее о типах данных см. perldoc perldata .)

Ссылка - это просто конкретный тип скаляра. The built-in function ref will tell you what kind of reference it is. On the other hand, if you have a blessed reference, ref will only tell you the package name the reference was blessed into, not the actual core type of the data (blessed references can be hashrefs, arrayrefs or other things). You can use Scalar::Util 's reftype will tell you what type of reference it is:

use Scalar::Util qw(reftype);

my $x = bless {}, 'My::Foo';
my $y = { };

print "type of x: " . ref($x) . "\n";
print "type of y: " . ref($y) . "\n";
print "base type of x: " . reftype($x) . "\n";
print "base type of y: " . reftype($y) . "\n";

...produces the output:

type of x: My::Foo
type of y: HASH
base type of x: HASH
base type of y: HASH

For more information about the other types of references (e.g. coderef, arrayref etc), see this question: How can I get Perl's ref() function to return REF, IO, and LVALUE? and perldoc perlref.

Note: You should not use ref to implement code branches with a blessed object (e.g. $ref($a) eq "My::Foo" ? say "is a Foo object" : say "foo not defined";) -- if you need to make any decisions based on the type of a variable, use isa (i.e if ($a->isa("My::Foo") { ... or if ($a->can("foo") { ...). Also see polymorphism.

43
ответ дан 24 November 2019 в 19:30
поделиться

I например, полиморфизм вместо проверки чего-либо вручную:

use MooseX::Declare;

class Foo {
    use MooseX::MultiMethods;

    multi method foo (ArrayRef $arg){ say "arg is an array" }
    multi method foo (HashRef $arg) { say "arg is a hash" }
    multi method foo (Any $arg)     { say "arg is something else" }
}

Foo->new->foo([]); # arg is an array
Foo->new->foo(40); # arg is something else

Это намного эффективнее, чем проверка вручную, так как вы можете повторно использовать свои «проверки», как любое другое ограничение типа. Это означает, что если вы хотите обрабатывать массивы, хэши и четные числа меньше 42, вы просто пишете ограничение для «четных чисел меньше 42» и добавляете новый мультиметод для этого случая. На "вызывающий код" это не влияет.

Ваша библиотека типов:

package MyApp::Types;
use MooseX::Types -declare => ['EvenNumberLessThan42'];
use MooseX::Types::Moose qw(Num);

subtype EvenNumberLessThan42, as Num, where { $_ < 42 && $_ % 2 == 0 };

Затем заставьте Foo поддерживать это (в этом определении класса):

class Foo {
    use MyApp::Types qw(EvenNumberLessThan42);

    multi method foo (EvenNumberLessThan42 $arg) { say "arg is an even number less than 42" }
}

Затем Foo-> new-> foo (40) печатает arg - четное число меньше 42 вместо arg - что-то другое .

4
ответ дан 24 November 2019 в 19:30
поделиться

В какой-то момент я прочитал достаточно убедительный аргумент Perlmonks о том, что тестирование типа скаляра с помощью ref или reftype - плохая идея. Я не помню, кто выдвинул идею или ссылку. Извините.

Дело в том, что в Perl есть много механизмов, которые позволяют заставить данный скаляр действовать как все, что угодно. Если вы привяжете дескриптор файла, чтобы он действовал как хэш, проверка с помощью reftype сообщит вам, что у вас есть файловый ханл. Он не скажет вам, что вам нужно использовать его как хэш.

Итак, аргумент пошел, лучше использовать утку, чтобы узнать, что такое переменная.

Вместо:

sub foo {
    my $var = shift;
    my $type = reftype $var;

    my $result;
    if( $type eq 'HASH' ) {
        $result = $var->{foo};
    }
    elsif( $type eq 'ARRAY' ) {
        $result = $var->[3];
    }
    else {
        $result = 'foo';
    }

    return $result;
}

Вы должен делать что-то вроде этого:

sub foo {
    my $var = shift;
    my $type = reftype $var;

    my $result;

    eval {
        $result = $var->{foo};
        1; # guarantee a true result if code works.
    }
    or eval { 
        $result = $var->[3];
        1;
    }
    or do {
        $result = 'foo';
    }

    return $result;
}

По большей части я этого не делаю, но в некоторых случаях делаю. Я' Я все еще думаю, когда этот подход уместен. Я подумал, что выброшу концепцию для дальнейшего обсуждения. Мне бы очень хотелось увидеть комментарии.

Обновление

Я понял, что должен изложить свои мысли по поводу этого подхода.

Этот метод имеет преимущество в обработке всего, что вы в него бросаете.

У него есть недостаток. быть громоздким и несколько странным. Если бы я наткнулся на это в каком-то коде, я бы выдал большой жирный «WTF».

Мне нравится идея проверить, действует ли скаляр как хэш-ссылка, а не хеш-ссылка. .

Мне не нравится эта реализация.

Обновление

Я понял, что должен изложить свои мысли об этом подходе.

Этот метод имеет преимущество обработки всего, что вы в него бросаете.

Недостатком этого метода является громоздкость и несколько странность. Если бы я наткнулся на это в каком-то коде, я бы выдал большой жирный «WTF».

Мне нравится идея проверить, действует ли скаляр как хэш-ссылка, а не хеш-ссылка .

Мне не нравится эта реализация.

Обновление

Я понял, что должен изложить свои мысли по поводу этого подхода.

Этот метод имеет то преимущество, что справляется со всем, что вы в него бросаете.

Недостатком этого метода является громоздкость и несколько странность. Если бы я наткнулся на это в каком-то коде, я бы выдал большой жирный «WTF».

Мне нравится идея проверить, действует ли скаляр как хэш-ссылка, а не хеш-ссылка .

Мне не нравится эта реализация.

2
ответ дан 24 November 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: