Estoy seguro de que esto está cubierto en la documentación en alguna parte, pero no he podido encontrarlo ... Estoy buscando el azúcar sintáctico que permitirá llamar a un método en una clase cuyo nombre está almacenado en una almohadilla (en contraposición a un simple escalar):¿Cómo llamo a un nombre de función que está almacenado en un hash en Perl?
use strict; use warnings;
package Foo;
sub foo { print "in foo()\n" }
package main;
my %hash = (func => 'foo');
Foo->$hash{func};
Si copio $hash{func}
en una variable escalar primero, entonces yo puedo llamar Foo->$func
muy bien ... pero lo que falta para que Foo->$hash{func}
a trabajar?
(EDITAR: No me refiero a hacer nada especial al llamar a un método en la clase Foo
- esto podría ser un objeto bendito (y en mi código real), simplemente fue más fácil escribir un ejemplo autónomo utilizando un método de clase.)
EDIT 2: Para completar los comentarios a continuación, esto es lo que estoy haciendo en realidad (esto es en una biblioteca de azúcar atributo Moose, creado con Moose::Exporter) :
# adds an accessor to a sibling module
sub foreignTable
{
my ($meta, $table, %args) = @_;
my $class = 'MyApp::Dir1::Dir2::' . $table;
my $dbAccessor = lcfirst $table;
eval "require $class" or do { die "Can't load $class: [email protected]" };
$meta->add_attribute(
$table,
is => 'ro',
isa => $class,
init_arg => undef, # don't allow in constructor
lazy => 1,
predicate => 'has_' . $table,
default => sub {
my $this = shift;
$this->debug("in builder for $class");
### here's the line that uses a hash value as the method name
my @args = ($args{primaryKey} => $this->${\$args{primaryKey}});
push @args, (_dbObject => $this->_dbObject->$dbAccessor)
if $args{fkRelationshipExists};
$this->debug("passing these values to $class -> new: @args");
$class->new(@args);
},
);
}
he reemplazado por encima de la línea marcada con esto:
my $pk_accessor = $this->meta->find_attribute_by_name($args{primaryKey})->get_read_method_ref;
my @args = ($args{primaryKey} => $this->$pk_accessor);
PS. Me acabo de dar cuenta de que esta misma técnica (utilizando la clase meta de Moose para buscar el cifrado en lugar de asumir su convención de nomenclatura) no se puede usar para los predicados, ya que Class::MOP::Attribute no tiene un acceso similar get_predicate_method_ref
. :(
No creo que esto es posible debido a la orden de análisis de Perl. ¿Por qué no quieres copiar $ hash {func} en un escalar primero? –
No hay una razón en particular, excepto que parece innecesario, y este fue un rompecabezas interesante que me dejó perplejo. No lo creí simplemente porque no sabía la respuesta de que no había respuesta. :) (tl; versión dr: ¡porque tengo curiosidad!) – Ether
Er, me parece que si estás usando Moose, entonces sigues haciéndolo de la manera incorrecta. Una de las características de Moose es el modelo de metaobjeto sobre el que está basado ... Tengo la sensación de que hay un método que puede invocar para buscar el sub actual por nombre de cadena, que luego podría llamar, en lugar de utilizar cadenas simples . Aunque no lo sé por lo alto de la cabeza ... –