Re: Use cases for 'sub Pckg::func { }' ?
by tybalt89 (Monsignor) on Aug 01, 2020 at 02:44 UTC
|
Do you mean something like this?
https://rosettacode.org/wiki/Compiler/AST_interpreter#Perl
This reads in a flattened Abstract Syntax Tree (AST)
and generates from it a tree of perl objects it can
then run with a simple ->run method and polymorphism.
This does have a hash %variables that is shared between several of the subs in different packages(classes).
There is also this, a simpler tree based expression parser and evaluator that again
uses perl polymorphism to calculate a result from a tree of objects. I'm considering submitting this to
https://rosettacode.org/wiki/Arithmetic_evaluation
but I'm not sure if I will.
#!/usr/bin/perl
use strict; # https://rosettacode.org/wiki/Arithmetic_evaluation
use warnings;
sub node { bless [ splice @_, 1 ], shift }
sub error { die s/\G.*//sr =~ tr/\t/ /cr, "^ $_[0] !\n" }
sub want { /\G$_[1]/gc ? shift : error pop }
sub expr
{
/\G\h+/gc;
my $tree =
/\G\d+/gc ? node NUMBER => $& :
/\G\(/gc ? want expr(0), qr/\)/, 'Missing Right Paren' :
error 'Operand Expected';
$tree =
/\G\h+/gc ? $tree :
$_[0] <= 0 && /\G\+/gc ? node ADD => $tree, expr(1) :
$_[0] <= 0 && /\G\-/gc ? node SUBTRACT => $tree, expr(1) :
$_[0] <= 1 && /\G\*/gc ? node MULTIPLY => $tree, expr(2) :
$_[0] <= 1 && /\G\//gc ? node DIVIDE => $tree, expr(2) :
return $tree while 1;
}
sub ADD::value { $_[0][0]->value + $_[0][1]->value }
sub SUBTRACT::value { $_[0][0]->value - $_[0][1]->value }
sub MULTIPLY::value { $_[0][0]->value * $_[0][1]->value }
sub DIVIDE::value { $_[0][0]->value / $_[0][1]->value }
sub NUMBER::value { $_[0][0] }
sub NUMBER::show { "$_[0][0]\n" }
sub UNIVERSAL::show
{ ref($_[0]) . "\n" . join('', map $_->show, @{$_[0]}) =~ s/^/ /g
+mr }
while( <DATA> )
{
eval
{
print;
my $tree = want expr(0), "\n", 'Incomplete Parse';
print $tree->show, "value of tree = ", $tree->value, "\n\n";
} or print "$@\n";
}
__DATA__
(1+3)*7
42 +
( 33 + ( 7 * 8 )
123 456
foobar
7 / foobar
7 foobar
10 - 3 - 1
10 - (3 - 1)
2 * 3 + 4 * 5
2 + 3 * 4 + 5
((((( 7 / 4 )))))
((((( 7 / 4 ))))))))
2 + (3 + 4 no_names_allowed )
7 )
1 + 3 )
| [reply] [d/l] |
|
|
Didn't the requirement from Rosetta forbid the use of eval ?
I'm a bit puzzled why you need all those packages, instead of defining separate methods in the same namespace.
Tho I'm often not "skilled" enough to understand your code... ;-)
++ for creativity! =)
update
Ah, I think I got it, those packages are classes and you populate them with methods in a shorter syntax.
| [reply] |
|
|
I'm using the "block" eval, which is just a "try/catch" mechanism, so I can
"die" deep in parsing recursion and still be able to go on to the next test case. It's just a different
feature with the same name as the "string" eval, which is what they don't want to allow.
I could have used a hash to map operations to their proper subs, but why bother when perl already has a hash
that does that for me. "Polymorphism forever!" hehehe
"Ah, I think I got it," - yes, yes you do :)
| [reply] |
|
|
Re: Use cases for 'sub Pckg::func { }' ?
by jo37 (Curate) on Jul 31, 2020 at 21:13 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
package Foo;
sub new {
my $class = shift;
bless {@_}, $class;
}
package main;
use Data::Dump 'pp';
sub Foo::guts {
my $self = shift;
pp $self;
}
my $foo = Foo->new(foo => 'bar');
$foo->guts;
Greetings, -jo
$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
| [reply] [d/l] |
|
|
jo37 you are guilty of monkey patching eueueueueueueu, sirens howling, you find yourself in a Cave. It's the cellar where the King keeps his barrels of wine. To the northeast there is the red door. Below there is a trap door. Oooopppss sorry, that was the punishment for acting over a distance. Let's go again monkey-patchers. Resume... You are in the trolls cave. To the north there is the heavy rock door. Thorin enters. He is laughing...
bw, bliako
| [reply] |
|
|
| [reply] [d/l] |
|
|
#!/usr/bin/perl
use strict;
use warnings;
use LinkedList::Single;
sub format_node_data {
my ($id, $name) = @{$_[0]};
"[id:$id, name:$name]";
}
sub LinkedList::Single::print {
my $list = (shift)->clone;
for ($list->head; $list->has_next; $list->next) {
print format_node_data($list->node_data), " -> ";
}
print format_node_data($list->node_data), "\n";
}
my $list = LinkedList::Single->new([1, 'foo'], [2, 'bar'], [3, 'baz'])
+;
$list->print;
__DATA__
[id:1, name:foo] -> [id:2, name:bar] -> [id:3, name:baz]
Greetings, -jo
$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
| [reply] [d/l] |
Re: Use cases for 'sub Pckg::func { }' ?
by ikegami (Patriarch) on Jul 31, 2020 at 14:00 UTC
|
What are the use cases of that pattern?
The pattern you are observing is that the package directive controls the package in which code is compiled. sub X::foo { pp(\@_) } is simply not an exception to that. Effort to provide a special behaviour for sub X::foo { pp(\@_) } was not spent.
Put differently,
sub X::foo { pp(\@_) }
is short for
BEGIN { *X::foo = sub { pp(\@_) }; }
which is effectively what happens every time you import a symbol from a module (e.g. use X qw( foo );).
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
|
|
Re: Use cases for 'sub Pckg::func { }' ?
by perlfan (Parson) on Jul 31, 2020 at 02:19 UTC
|
Sounds like the foundations for Perl mixins. :) | [reply] |