Я попытался использовать метод функции из jbaron выше, но обнаружил, что мне нужно сохранить исходный массив без изменений для последующего использования, и создать новый массив, подобный этому:
var newArray = referenceArray;
, очевидно, создает по ссылке вместо значение, потому что, когда я удалил элемент из newArray, referenceArray также удалил его. Поэтому я решил каждый раз создавать новый массив следующим образом:
function newArrRemoveItem(array, item, newArray){
for(var i = 0; i < array.length; i++) {
if(array[i]!=item){
newArray.push(array[i]);
}
}
}
Затем я использую его следующим образом в другой функции:
var vesselID = record.get('VesselID');
var otherVessels = new Array();
newArrRemoveItem(vesselArr,vesselID,otherVessels);
Теперь vesselArr остается неизменным, а каждый раз - выполнить приведенный выше код, массив otherVessels включает в себя все, кроме самого последнего элемента vesselID.
Here is a version which works:
#!/usr/bin/perl
use strict;
use warnings;
my $class = 'Frew';
{
no strict 'refs';
*{ "${class}::INC" } = sub {
my ($self, $req) = @_;
return unless $req eq $class;
my $data = qq{
package $class;
sub foo { print "test!\n" };
1;
};
open my $fh, '<', \$data;
return $fh;
};
}
my $foo = bless { }, $class;
unshift @INC, $foo;
require $class;
$class->foo;
The @INC
hook gets the name of the file (or string passed to require
) as the second argument, and it gets called every time there is a require
or use
. So you have to check to make sure we're trying to load $classname
and ignore all other cases, in which case perl continues down along @INC
. Alternatively, you can put the hook at the end of @INC
. This was the cause of your recursion errors.
ETA: IMHO, a much better way to achieve this would be to simply build the symbol table dynamically, rather than generating code as a string. For example:
no strict 'refs';
*{ "${class}::foo" } = sub { print "test!\n" };
*{ "${class}::new" } = sub { return bless { }, $class };
my $foo = $class->new;
$foo->foo;
No use
or require
is necessary, nor messing with evil @INC
hooks.
В качестве простого примера того, как это сделать, прочтите исходный код Class :: Struct .
Однако, если мне понадобится возможность динамически создавать классы для какой-нибудь производственный код, я бы посмотрел на MooseX :: Declare, как предлагает jrockway.
A Perl class is little more than a data structure (usually a hashref) that has been blessed into a package in which one or more class methods are defined.
It is certainly possible to define multiple package namespaces in one
file; I don't see why this wouldn't be possible in an eval
construct
который компилируется во время выполнения (см. perlfunc
для двух разных
eval
форм).
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use Data::Dumper;
eval q[
package Foo;
sub new {
my ( $class, %args ) = @_;
my $self = bless { %args }, $class;
return $self;
}
1;
];
die $@ if $@;
my $foo = Foo->new(bar => 1, baz => 2) or die;
say Dumper $foo;
Я делаю это:
use MooseX::Declare;
my $class = class {
has 'foo' => (is => 'ro', isa => 'Str', required => 1);
method bar() {
say "Hello, world; foo is ", $self->foo;
}
};
Затем вы можете использовать $ class, как любой другой метакласс:
my $instance = $class->name->new( foo => 'foo bar' );
$instance->foo; # foo-bar
$instance->bar; # Hello, world; foo is foo-bar
и т. Д.
Если вы хотите динамически генерировать классы во время выполнения, вам нужно создать соответствующий метакласс, создайте его экземпляр, а затем используйте экземпляр метакласса для создания экземпляров. Базовый ОО. Class :: MOP обрабатывает все детали за вас:
my $class = Class::MOP::Class->create_anon_class;
$class->add_method( foo => sub { say "Hello from foo" } );
my $instance = $class->new_object;
...
Если вы хотите сделать это самостоятельно, чтобы вы могли тратить свое время на отладку чего-либо, возможно, попробуйте:
sub generate_class_name {
state $i = 0;
return '__ANON__::'. $i++;
}
my $classname = generate_class_name();
eval qq{
package $classname;
sub new { my \$class = shift; bless {} => \$class }
...
};
my $instance = $classname->new;