More Related Content Similar to Perl Sucks - and what to do about it (20) Perl Sucks - and what to do about it2. What this talk is not
• “Wah, no one uses ‘use strict’”
• “People’s perception of Perl is wrong”
• “The CPAN/mailing list/a other website
isn’t exactly how I like it”
• “The garbage collection de-allocation
routine isn’t very efficent” 3. What this talk is
• What’s a few major annoyances with Perl
• What we the humble programmer can do to
work around them 14. Make an executable
• perl -MCPAN -e ‘install PAR::Packer’
• pp -o hellow hellow.pl
• ...copy “hellow” to new computer
• ./hellow
Hello World 19. Get Stable Perl
• lwp-request $CPAN_URL >
perl-5.8.8.tar.gz
• gunzip -c perl-5.8.8.tar.gz | tar -xvf -
• cd perl-5.8.8 20. Tell it where to go
• mkdir -p /User/mark/bin/perl5.8.8
• ./configure.gnu --prefix=/User/mark/bin/
perl5.8.8 28. Can't locate Storable.pm in @INC (@INC
contains: /User/mark/bin/perl5.8.8/lib/5.8.8/
darwin-2level /User/mark/bin/perl5.8.8/lib/
5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/
5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/
site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/
site_perl .) at -e line 1. 29. Can't locate Storable.pm in @INC (@INC
contains: /User/mark/bin/perl5.8.8/lib/5.8.8/
darwin-2level /User/mark/bin/perl5.8.8/lib/
5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/
5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/
site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/
site_perl .) at -e line 1. 30. Can't locate Storable.pm in @INC (@INC
contains: ../lib/5.8.8/darwin-2level
../lib/5.8.8
../lib/site_perl/5.8.8/darwin-2level
../lib/site_perl/5.8.8
../lib/site_perl .) at -e line 1. 32. B
E
TA
Get Bleed Perl
• lwp-request $CPAN_URL >
perl-5.9.5.tar.gz
• gunzip -c perl-5.9.5.tar.gz | tar -xvf -
• cd perl-5.9.5 33. B
E
TA
Tell it where to go
• mkdir -p /User/mark/bin/perl5.9.5
• ./Configure -Dusedevel -Dprefix=/User/
mark/bin/perl5.9.5 -Duserelocatableinc -d 34. B
E
TA
Tell it where to go
• mkdir -p /User/mark/bin/perl5.9.5
• ./Configure -Dusedevel -Dprefix=/User/
mark/bin/perl5.9.5 -Duserelocatableinc -d 35. B
E
TA
Install it
• make
• make test
• make install 36. B
E
TA
mv ~/bin/perl5.9.5
whatever 37. B
E
TA
whatever/bin/perl5.9.5
-e ‘use Storable’ 39. Java
try {
throw new NoCheeseException(“redo”);
} catch (NoCheeseException e) {
system.err.println(e.toString());
} 40. Perl
eval {
die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
$@->isa(“NoCheeseException”)) {
print STDERR $@;
} elsif ($@) { die $@ } 43. Perl
eval {
die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
$@->isa(“NoCheeseException”)) {
print STDERR $@;
} elsif ($@) { die $@ } 46. Perl
eval {
die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
$@->isa(“NoCheeseException”)) {
print STDERR $@;
} elsif ($@) { die $@ } 48. eval {
# run some code to catch errors in
}; 49. Perl
eval {
die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
$@->isa(“NoCheeseException”)) {
print STDERR $@;
} elsif ($@) { die $@ } 50. Perl
eval {
die new NoCheeseError->new(“redo”);
};
if (blessed($@) &&
$@->isa(“NoCheeseException”)) {
print STDERR $@;
} elsif ($@) { die $@ } 52. (still) Perl
try {
throw NoCheeseException “redo”;
}
catch NoCheeseException with {
print STDERR $@;
}; 53. try {
throw NoCheeseException “redo”;
}
catch NoCheeseException with {
print STDERR $@;
}
catch AnotherError with {
print STDERR “oopsn”;
}; 54. try {
throw NoCheeseException “redo”;
}
catch NoCheeseException with {
print STDERR $@;
}
catch AnotherError with {
print STDERR “oopsn”;
}; 55. try( sub {
throw NoCheeseException “redo”;
},
catch NoCheeseException with(sub {
print STDERR $@;
},
catch AnotherError with(sub {
print STDERR “oopsn”;
}))); 56. try( sub {
throw NoCheeseException “redo”;
},
catch NoCheeseException with(sub {
print STDERR $@;
},
catch AnotherError with(sub {
print STDERR “oopsn”;
}))); 57. try( sub {
NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( with(sub {
print STDERR $@;
},
AnotherError->catch( with(sub {
print STDERR “oopsn”;
}))))); 59. try( sub {
NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( with(sub {
print STDERR $@;
},
AnotherError->catch( with(sub {
print STDERR “oopsn”;
}))))); 60. try( sub {
NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
print STDERR $@;
},
AnotherError->catch( sub {
print STDERR “oopsn”;
}))); 62. try( sub {
NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
print STDERR $@;
},
AnotherError->catch( sub {
print STDERR “oopsn”;
}))); 63. try( sub {
NoCheeseException->throw( “redo” );
},
NoCheeseException->catch( sub {
print STDERR $@;
}, +{
class => “AnotherError”,
action => sub { print STDERR “oopsn” }
})); 64. try( sub {
NoCheeseException->throw( “redo” );
}, +{
class => “NoCheeseException”,
action => sub { print STDERR $@; }
}, +{
class => “AnotherError”,
action => sub { print STDERR “oopsn” }
}); 65. try( sub {
NoCheeseException->throw( “redo” );
}, +{
class => “NoCheeseException”,
action => sub { print STDERR $@; }
}, +{
class => “AnotherError”,
action => sub { print STDERR “oopsn” }
}); 66. try( sub {
NoCheeseException->throw( “redo” );
}, +{
class => “NoCheeseException”,
action => sub { print STDERR $@; }
}, +{
class => “AnotherError”,
action => sub { print STDERR “oopsn” }
}); 67. try( sub {
NoCheeseException->throw( “redo” );
}, +{
class => “NoCheeseException”,
action => sub { print STDERR $@; }
}, +{
class => “AnotherError”,
action => sub { print STDERR “oopsn” }
}); 68. (still) Perl
try {
throw NoCheeseException “redo”;
}
catch NoCheeseException with {
print STDERR $@;
}; 69. sub foo {
try {
return “This doesn’t return from foo”;
}
catch NoCheeseException with {
print STDERR $@;
};
} 70. sub foo {
eval {
return “This doesn’t return from foo”;
};
if ($@) { .... }
} 71. sub foo {
try {
return “This doesn’t return from foo”;
}
catch NoCheeseException with {
print STDERR $@;
};
} 72. sub foo {
try {
rreturn “This doesn’t return from foo”;
}
catch NoCheeseException with {
print STDERR $@;
} and return allowed;
} 73. sub foo {
try {
rreturn “This doesn’t return from foo”;
}
catch NoCheeseException with {
print STDERR $@;
} and return allowed;
} 74. MyException
NoDairyException
NoSpreadException
NoMilkException
NoButterException
NoMargException
NoCheeseException
NoEdamException NoStiltonException NoBrieException 75. package NoDairyException;
our @ISA = qw(MyError);
package NoMilkException;
our @ISA = qw(NoDairyException);
package NoSpreadException;
our @ISA = qw(NoDairyException);
package NoButterException;
our @ISA = qw(NoSpreadException);
package NoMargException;
our @ISA = qw(NoMargeException);
package NoCheeseException;
our @ISA = qw(NoDairyException);
package NoEdamException;
our @ISA = qw(NoCheeseException);
package NoStiltonException;
our @ISA = qw(NoCheeseException);
package NoBrieException;
our@ISA = qw(NoCheeseException); 76. Exceptions::define {
exception NoDairyException;
exception NoSpreadException extends NoDairyException;
exception NoButterException extends NoSpreadException;
exception NoMargException extends NoSpreadException;
exception NoMilkException extends NoDairyException;
exception NoCheeseException extends NoDairyException;
exception NoEdamException extends NoCheeseException;
exception NoStiltonException extends NoCheeseException;
exception NoBrieException extends NoCheeseException;
}; 84. where bash finds the
Executable code to
#!tpage load into memory
[% whereami = “Vienna” -%]
Hello [% whereami %]! 88. • “Source filters are a way to change your
source code before perl gets to see it” 99. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq'oh hain’;quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 100. ( stolen from
“perldoc perlembed”) 101. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq'o hain';quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 102. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq’o hain’;quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 103. cc -o hellow hellow.c `perl -MExtUtils::Embed -e ccopts -e ldopts` 105. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq'o hain';quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 106. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq’o hain’;quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 107. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]};
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 4, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq’o hain’;quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 108. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]};
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 4, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv(quot;print qq’o hain’;quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 109. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]};
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 4, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv( “use Template
Template->new->process($ARGV[0])quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 110. cc -o mytt mytt.c `perl -MExtUtils::Embed -e ccopts -e ldopts` 111. now Executable code to
load into memory
#!mytt
[% whereami = “Vienna” -%]
Hello [% whereami %]! 112. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
“hellov.tp”
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]};
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 4, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv( “use Template
Template->new->process($ARGV[0])quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 113. #include <EXTERN.h>
#include <perl.h>
static PerlInterpreter *my_perl;
“hellov.tp”
int main(int argc, char **argv, char **env)
{
char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, argv[0]};
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 4, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
eval_pv( “use Template
Template->new->process($ARGV[0])quot;, TRUE);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
} 115. A
LP
H
A
We’ve already seen
source filters 116. B
E
TA
PPI
• Pure Perl parser
• Only parses a subset of Perl
• Can’t tell the difference between certain
Perl constructs
• This said - very very good at what it does 118. A
LP
H
A
./configure.gnu --prefix=~/bin/perl595
-Dusedevel -Dmad=y
make && make test && make install 119. A
LP
H
A
my $a = 1;
my $b = 2;
print $a + $b; 120. A
LP
H
A
PERL_XMLDUMP=quot;foo.xmlquot; ./perl foo.pl 121. </op_nextstate>
A
LP
<op_sassign seq=quot;9 -> 10quot;
H
flags=quot;VOID,KIDS,STACKEDquot;> A
<op_leave seq=quot;0 -> DONEquot; targ=quot;1quot; flags=quot;VOID,KIDS,PARENSquot;
private=quot;REFCOUNTEDquot;
refcnt=quot;1quot;>
<op_enter seq=quot;1 -> 2quot; />
<op_null seq=quot;0 -> (2)quot; flags=quot;VOIDquot;>
<madprops>
<mad_sv key=quot;;quot; val=quot;quot;/>
</madprops>
<madprops>
</op_null>
<op_nextstate seq=quot;2 -> 3quot; flags=quot;VOIDquot;
line=quot;1quot;
package=quot;mainquot;>
<madprops>
<mad_sv key=quot;;quot; val=quot;;quot;/>
<mad_sv key=quot;#;quot; val=quot;
quot;/>
</madprops>
<mad_sv key=quot;oquot; val=quot;=quot;/>
</op_nextstate>
<op_sassign seq=quot;5 -> 6quot; flags=quot;VOID,KIDS,STACKEDquot;>
<madprops>
<mad_sv key=quot;oquot; val=quot;=quot;/>
<mad_sv key=quot;_oquot; val=quot; quot;/>
</madprops>
<op_const seq=quot;3 -> 4quot; flags=quot;SCALARquot;
IV=quot;1quot;>
<mad_sv key=quot;_oquot; val=quot; quot;/>
<madprops>
<mad_sv key=quot;Xquot; val=quot;1quot;/>
<mad_sv key=quot;_Xquot; val=quot; quot;/>
</madprops>
</op_const>
<op_padsv seq=quot;4 -> 5quot; targ=quot;1quot; flags=quot;SCALAR,REF,MOD,SPECIALquot;
private=quot;INTROquot;>
<madprops>
</madprops>
<mad_sv key=quot;$quot; val=quot;$aquot;/>
<mad_sv key=quot;_$quot; val=quot; quot;/>
<mad_sv key=quot;dquot; val=quot;myquot;/>
<mad_sv key=quot;_dquot; val=quot;quot;/>
</madprops>
</op_padsv>
</op_sassign>
<op_nextstate seq=quot;6 -> 7quot; flags=quot;VOIDquot;
<op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot;
line=quot;2quot;
package=quot;mainquot;>
<madprops>
<mad_sv key=quot;;quot; val=quot;;quot;/>
<mad_sv key=quot;#;quot; val=quot;
quot;/>
</madprops>
</op_nextstate>
<op_sassign seq=quot;9 -> 10quot; flags=quot;VOID,KIDS,STACKEDquot;>
<madprops>
IV=quot;2quot;>
<mad_sv key=quot;oquot; val=quot;=quot;/>
<mad_sv key=quot;_oquot; val=quot; quot;/>
</madprops>
<op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot;
IV=quot;2quot;>
<madprops>
<mad_sv key=quot;Xquot; val=quot;2quot;/>
<mad_sv key=quot;_Xquot; val=quot; quot;/>
<madprops>
</madprops>
</op_const>
<op_padsv seq=quot;8 -> 9quot; targ=quot;2quot; flags=quot;SCALAR,REF,MOD,SPECIALquot;
private=quot;INTROquot;>
<madprops>
<mad_sv key=quot;$quot; val=quot;$bquot;/>
<mad_sv key=quot;_$quot; val=quot; quot;/>
<mad_sv key=quot;dquot; val=quot;myquot;/>
<mad_sv key=quot;Xquot; val=quot;2quot;/>
</madprops>
</op_padsv>
</op_sassign>
<op_nextstate seq=quot;10 -> 11quot; flags=quot;VOIDquot;
line=quot;3quot;
package=quot;mainquot;>
<madprops>
<mad_sv key=quot;;quot; val=quot;;quot;/>
<mad_sv key=quot;_Xquot; val=quot; quot;/>
<mad_sv key=quot;_;quot; val=quot;quot;/>
<mad_sv key=quot;#;quot; val=quot;
quot;/>
</madprops>
</op_nextstate>
<op_print seq=quot;15 -> 16quot; flags=quot;SCALAR,KIDSquot;>
<madprops>
<mad_sv key=quot;oquot; val=quot;printquot;/>
</madprops>
</madprops>
<op_pushmark seq=quot;11 -> 12quot; flags=quot;SCALARquot; />
<op_add seq=quot;14 -> 15quot; targ=quot;3quot; flags=quot;SCALAR,KIDSquot;>
<madprops>
<mad_sv key=quot;oquot; val=quot;+quot;/>
<mad_sv key=quot;_oquot; val=quot; quot;/>
</madprops>
<op_padsv seq=quot;12 -> 13quot; targ=quot;1quot; flags=quot;SCALARquot;>
<madprops>
</op_const>
<mad_sv key=quot;$quot; val=quot;$aquot;/>
<mad_sv key=quot;_$quot; val=quot; quot;/>
</madprops>
</op_padsv>
<op_padsv seq=quot;13 -> 14quot; targ=quot;2quot; flags=quot;SCALARquot;>
<madprops>
<mad_sv key=quot;$quot; val=quot;$bquot;/>
<mad_sv key=quot;_$quot; val=quot; quot;/>
</madprops>
<op_padsv seq=quot;8 -> 9quot; targ=quot;2quot;
</op_padsv>
</op_add>
</op_print>
<op_null seq=quot;0 -> (16)quot; flags=quot;VOIDquot; />
</op_leave>
flags=quot;SCALAR,REF,MOD,SPECIALquot; 123. use B::Generate;
# Do nothing, slowly.
CHECK {
my $null = new B::OP(quot;nullquot;,0);
my $enter = new B::OP(quot;enterquot;,0);
my $cop = new B::COP(0, quot;hiyaquot;, 0);
my $leave = new B::LISTOP(quot;leavequot;, 0, $enter, $null);
$leave->children(3);
$enter->sibling($cop);
$enter->next($cop);
$cop->sibling($null);
$null->next($leave);
$cop->next($leave);
# Tell Perl where to find our tree.
B::main_root($leave);
B::main_start($enter);
} 124. optomize.pm
• Can be used to manipulate the OP codes
after they’ve loaded
• Kinda like source filters for compiled
bypecode 125. Use?
• PPI is reliable, but limited in it’s ability
• Easy to try to do too much with
• Other techniques are very unstable / new
• B::Generate
• optomize
• MAD 127. A
LP
H
A
package main;
use typesafety; # 'summary', 'debug';
my FooBar $foo; # establish type-checked variables
my FooBar $bar; # FooBar is the base class of references $bar will hold
my BazQux $baz;
$foo = new FooBar; # this is okay, because $foo holds FooBars
$bar = $foo; # this is okay, because $bar also holds FooBars
# $foo = 10; # this would throw an error - 10 is not a FooBar
# $baz = $foo; # not allowed - FooBar isn't a BazQux
$foo = $baz; # is allowed - BazQux is a FooBar because of inheritance
$bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also
typesafety::check(); # perform type check static analysis 128. A
LP
H
A
package main;
use typesafety; # 'summary', 'debug';
my FooBar $foo; # establish type-checked variables
my FooBar $bar; # FooBar is the base class of references $bar will hold
my BazQux $baz;
$foo = new FooBar; # this is okay, because $foo holds FooBars
$bar = $foo; # this is okay, because $bar also holds FooBars
# $foo = 10; # this would throw an error - 10 is not a FooBar
# $baz = $foo; # not allowed - FooBar isn't a BazQux
$foo = $baz; # is allowed - BazQux is a FooBar because of inheritance
$bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also
typesafety::check(); # perform type check static analysis 129. A
LP
H
A
package main;
use typesafety; # 'summary', 'debug';
my FooBar $foo; # establish type-checked variables
my FooBar $bar; # FooBar is the base class of references $bar will hold
my BazQux $baz;
$foo = new FooBar; # this is okay, because $foo holds FooBars
$bar = $foo; # this is okay, because $bar also holds FooBars
# $foo = 10; # this would throw an error - 10 is not a FooBar
# $baz = $foo; # not allowed - FooBar isn't a BazQux
$foo = $baz; # is allowed - BazQux is a FooBar because of inheritance
$bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also
typesafety::check(); # perform type check static analysis 130. A
LP
H
A
package main;
use typesafety; # 'summary', 'debug';
my FooBar $foo; # establish type-checked variables
my FooBar $bar; # FooBar is the base class of references $bar will hold
my BazQux $baz;
$foo = new FooBar; # this is okay, because $foo holds FooBars
$bar = $foo; # this is okay, because $bar also holds FooBars
# $foo = 10; # this would throw an error - 10 is not a FooBar
# $baz = $foo; # not allowed - FooBar isn't a BazQux
$foo = $baz; # is allowed - BazQux is a FooBar because of inheritance
$bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also
typesafety::check(); # perform type check static analysis