2016-11-14 10 views
-1

У меня есть код, который в основном:Perl 5 - оценка кода OO в строке

$object = Class->new(); 
$message = 'get_value': 

Я хочу запустить $object->$message(); Но я не могу получить, что для компиляции, так что я пытаюсь

my $value = eval '$object->$message()'; 

Но это всегда возвращает undef.

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

+0

Что вы на самом деле пытаетесь сделать здесь? Почему вы пытаетесь создать динамическое имя sub? Более распространенным подходом будет '$ object -> get_value ($ some_attribute_name)' или что-то подобное. Это похоже на проблему [XY] (http: //meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Sobrique

+3

Это должно сработать. Вы не показываете свой настоящий код. – simbabque

+0

Хорошо пятнистый. Я отправился на поиски проблемы, прежде чем понял, что ее нет. – Sobrique

ответ

3

Я думаю, все зависит от того, что вы пытаетесь выполнить. Это выглядит как XY Problem

Более обычным подходом было бы, например,

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

package MyObject; 

sub new { 
    my ($class, %args) = @_; 
    my $self = {}; 
    $self->{args} = \%args; 
    bless $self, $class; 
    return $self; 
} 

sub get_value { 
    my ($self, $attribute) = @_; 
    return $self -> {args} -> {$attribute}; 
} 

package main; 

my $object = 'MyObject'->new(test => 'frobnicated', foo=>'bar'); 
print $object -> get_value('test'); 

И обрабатывать динамический бит в самом методе, например.

Однако, если вы хотите, чтобы «найти» подпрограмму можно использовать метод can получить coderef:

my $methodname = 'get_value'; 
if (my $coderef = $object -> can($methodname)) { 
    print $coderef -> ($object,'foo'); 
} 

я не уверен, this'd в целом хорошая вещь, чтобы делать хотя, поскольку это могло стать довольно грязным. Я думаю, что этот подход менее вероятен для случайного разрыва, чем для eval.

Однако ваш оригинальный подход делает работы:

my $value = eval '$object->$methodname("foo")'; 
print $value,"\n"; 

Я думаю, что это может быть, что ваш саб erroring - вы пробовали проверять [email protected], который является кодом возврата eval?

+0

Важна проверка Ahah :-(Хорошая точка, спасибо. –

+0

'my $ value = eval '$ object -> $ methodname (" foo ")'; print $ value," \ n ";' дает мне синтаксическую ошибку около $ самости 'югу ПОЛУЧАЕТ { \t моего $ самообеспечения = сдвиг;? \t моих% Args = (исе ($ _ [0]) 'HASH' э)% {$ _ [0] }: @_; \t возврат, если ($ арг { 'объект'} && $ арг { 'сообщение'}); \t мой $ а = $ аргументов { 'объект'}; \t моего $ м = $ args {'message'} \t my $ rc = eval '$ o -> $ m()'; \t die $ @ if $ @; return $ rc; } ' –

+2

@NigelHorne: Пожалуйста, не вводите код в комментарии. Это почти невозможно понять. Пожалуйста, отредактируйте свой вопрос] (http://stackoverflow.com/posts/40590650/edit), чтобы добавить его там. –

1

Ваша первоначальная версия должна работать нормально.

#!/usr/bin/perl 

use strict; 
use warnings; 

package Class; 

sub new { 
    return bless { value => $_[1] }, $_[0]; 
} 

sub get_value { 
    return $_[0]->{value}; 
} 

package main; 

my $obj = Class->new('some value'); 
my $message = 'get_value'; 

print $obj->$message(); 

Это работает точно так, как ожидалось, и печатает «какое-то значение». Нет необходимости использовать eval.

От perldoc perlobj:

Названия методов, как Струны

Perl позволяет использовать скалярную переменную, содержащую строку в качестве имени метода :

my $file = File->new($path, $data); 

my $method = 'save'; 
$file->$method(); 

Это работает так же, как позвонив по телефону $file->save(). Это может быть очень полезно для написания динамического кода. Например, он позволяет передать имя метода, которое будет вызываться как параметр, другому методу.

Таким образом, проблема в другом месте вашего кода.