Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pointer to constructor to a class in perl6

Tags:

class

raku

I am trying to write some classes with Perl 6 just for testing out Perl 6 classes and methods.

Here is the code:

class human1 {
    method fn1() {
        print "#from human1.fn1\n";
    }
}

class human2 {
    method fn1() {
          print "#from human2.fn1\n";
    }
}

my $a = human1.new();
my $b = human2.new();

$a.fn1();
$b.fn1();

print "now trying more complex stuff\n";

my $hum1_const = &human1.new;
my $hum2_const = &human2.new;

my $c = $hum2_const();
$c.fn1();

Essentially I want to be able to use either the human1 constructor or human2 constructor to be able to build $c object dynamically. But I'm getting the following error:

Error while compiling /usr/bhaskars/code/perl/./a.pl6
Illegally post-declared types:
    human1 used at line 23
    human2 used at line 24

How do I create $c using the function pointers to choose which constructor I use?

like image 644
BhaskarS Avatar asked Dec 27 '17 14:12

BhaskarS


2 Answers

To get a “reference” to .new you have to use the meta object protocol.
Either .^lookup, or .^find_method.

my $hum1-create = human1.^find_method('new');

That is still not quite what you are looking for, as methods require either a class object or an instance, as their first argument.

my $c = $hum1-create( human1 );

So you would probably want to curry the class as the first argument to the method.

my $hum1-create = human1.^find_method('new').assuming(human1);

my $c = $hum1-create();

Note that .assuming in this case basically does the same thing as

-> |capture { human1.^find_method('new').( human1, |capture ) }

So you could just write:

my $hum1-create = -> |capture { human1.new( |capture ) }

Or if you are never going to give it an argument

my $hum1-create = -> { human1.new }

Also you can store it in a & sigiled variable, so you can use it as if it were a normal subroutine.

my &hum1-create = human1.^find_method('new').assuming(human1);

my $c = hum1-create;
like image 82
Brad Gilbert Avatar answered Nov 02 '22 20:11

Brad Gilbert


I think this is a case of an LTA error. What I understand you want to achieve, is a lambda that will create a new human1 or human2 object for you. The way you do that is not correct, and the error it causes is confusing.

my $hum1_const = -> { human1.new };
my $hum2_const = -> { human2.new };

would be a correct way of doing this. Although, I would consider this a bit of an obfuscation. Since human1 and human2 are already constants, you can assign them to a variable, and then just call new on that:

my $the_human = $condition ?? human1 !! human2;
my $c = $the_human.new;
$c.fn1;

Does that make sense?

like image 27
Elizabeth Mattijsen Avatar answered Nov 02 '22 20:11

Elizabeth Mattijsen