Tengo dificultades para usar MooseX :: Declare correctamente cuando llamo a BUILDARGS.¿Cuál es la forma correcta de crear un método BUILDARGS utilizando MooseX :: Declare?
Estoy intentando crear un objeto como una interfaz para un archivo. (Específicamente, quiero una interfaz para un archivo binario que me permita echar un vistazo a los siguientes bytes en el archivo y luego cortarlos para su posterior procesamiento.)
Quiero ser capaz de crear uno de estos objetos como este
my $f = binary_file_buffer->new($file_name);
y luego usarlo como esto
while(my $block_id = $f->peek($id_offset, $id_length)) {
$block_id = unpack_block_id($block_id);
$munge_block{ $block_id }->(
$f->pop($block_size[ $block_id ])
);
}
Mi binary_file_buffer de definición de clase/declaración se parece a esto
use MooseX::Declare;
class binary_file_buffer {
use FileHandle;
use Carp;
has _file => (is => 'ro', isa => 'FileHandle');
has _file_name => (is => 'ro', isa => 'Str');
has _buff => (is => 'rw', isa => 'Str', default => '');
method BUILDARGS (Str $file_name) {
my $file = FileHandle->new($file_name);
carp "unable to open $file_name : $!" unless defined $file;
$file->binmode;
return (
_file_name => $file_name,
_file => $file,
);
}
# get the next n bytes from the buffer.
method pop (Int $len) {
# ... Make sure there is data in _buff
return substr($self->{_buff}, 0, $len, '');
}
# Look around inside the buffer without changing the location for pop
method peek (Int $offset, Int $len) {
# ... Make sure there is data in _buff
return substr($self->{_buff}, $offset, $len);
}
}
(No es tampón de carga y el código de gestión que no he incluido aquí. Es bastante sencillo.)
El problema es que utilizo la palabra clave method
en la declaración BUILDARGS
. Así, MooseX :: Declare espera un objetobinary_file_buffer
como primer argumento a BUILDARGS
. Pero BUILDARGS
obtiene los argumentos que se pasan a la nueva, por lo que el primer argumento es la cadena un 'binary_file_buffer'
, el nombre del paquete. Como resultado, falla el tipo de comprobación y se agota al crear un objeto utilizando new, como hice en el primer fragmento de código. (Al menos esa es mi comprensión de lo que está sucediendo.)
El mensaje de error que consigo es:
Validation failed for 'MooseX::Types::Structured::Tuple[MooseX::Types::Structured::Tuple[Object,Str,Bool],MooseX::Types::Structured::Dict[]]' failed with value [ [ "binary_file_buffer", "drap_iono_t1.log", 0 ], { } ], Internal Validation Error is: Validation failed for 'MooseX::Types::Structured::Tuple[Object,Str,Bool]' failed with value [ "binary_file_buffer", "drap_iono_t1.log", 0 ] at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 445
MooseX::Method::Signatures::Meta::Method::validate('MooseX::Method::Signatures::Meta::Method=HASH(0x2a623b4)', 'ARRAY(0x2a62764)') called at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 145
binary_file_buffer::BUILDARGS('binary_file_buffer', 'drap_iono_t1.log') called at generated method (unknown origin) line 5
binary_file_buffer::new('binary_file_buffer', 'drap_iono_t1.log') called at logshred.pl line 13
me gusta la comprobación de tipos de azúcar las method
suministros de palabras clave por $ nombre_archivo, pero no sé cómo obtenerlo desde BUILDARGS
no es técnicamente un método.
¿El MooseX :: Declarar tener una forma de omitir la creación $self
, o algo por el estilo?
estoy haciendo esto el MooseX adecuada :: Declarar manera? ¿O me estoy perdiendo algo?
Bingo! Eso hace exactamente lo que quiero. Me perdí 2 cosas en los documentos que tu respuesta aclaró. En primer lugar, no vi el subtipo ClassName de Str en Moose :: Manual :: Types docs. No esperaba un subtipo de cadena ClassName incorporado. En segundo lugar, no vi que los documentos MooseX :: Method :: Signatures muestren cómo nombrar el invocador de un método y declarar su tipo. No me di cuenta de que la sintaxis de la firma del método que usa MooseX :: Declare es del paquete MooseX :: Method :: Signatures. Hasta ahora, amo MooseX :: Declare. Sabía que había una manera de Moose para hacer lo que quería. Simplemente no pude entender cómo. Gracias. – meta4
Usar ClassName en lugar de Object para method/around debería escribirse en algún lugar del manual de MooseX :: Declare ... también fue mordido por esto – anydot