a necessary no-op

I've got a weird one here... a line that looks like it does
nothing significant is needed for the code to work.
If the line below marked "The Mystery Line" is commented out,
you just get the error:

   ===SORRY!===
   Cannot look up attributes in a VMNull type object

Augment::Util:

class Recomposer {
    method recompose_core {
        my @type_symbols = (|CORE::).grep({ .key eq .value.^name
}).map( *.value );
        for @type_symbols -> $type_symbol {
            my $type_symbol_name = $type_symbol.^name;
            try {
                my $nada = $type_symbol.gist;  # The Mystery Line
                $type_symbol.^compose;
                # if there's no ^.compose method, just skip to next
type symbol object
                CATCH {
                    default { }
                }
            }
        }
    }
}


The problem seems to be local to that "recompose_core" routine,
though just to be complete I'll tack on the rest of my code...
sorry about the length, it's hard to strip it down much further
than this.

The goal here is to be able to start the repl with the command:

  perl6 -Mmethod-menu

And have a new method (something like .^methods) named simply .m
available everywhere.


method-menu:

use Object::Examine;
use Augment::Util;
use MONKEY-TYPING;
augment class Any does Introspector {
    method m {
        return self.menu;
    }
    Recomposer.recompose_core();
}


Object::Examine:

role Introspector {
    method menu {
        my @seen_methods = ();
        my @levels  = self.^mro; # better than ^parents: current class and above
        my $report = '';
        my @data;
        for @levels -> $l {
            my $level_name     = $l.^name;
            my @current_methods  = clean_methods( methods_for( $l ) );
            my @child_methods = ( @current_methods (-) @seen_methods ).keys;
            # saving up the data...
            for @child_methods -> $cm {
                @data.push([$cm, $level_name]);
            }
            @seen_methods = ( @seen_methods (+) @current_methods ).keys;
        }
        my @lines = @data.sort({ $_[0] });
        for @lines -> $l {
            my $fmt = "%-25s %-25s\n";
            $report ~= sprintf $fmt, $l[0], $l[1];
        }
        return $report;
    }
    sub methods_for(Mu $obj) {
        my @raws = $obj.^methods(:local);  # or :all?
    }
    sub clean_methods (@raws) {
        my @strs = @raws.map({ .gist });
        my @ways = @strs.sort;
        my @unis = @ways.unique;
        # filter out methods 'Method+{is-nodal}.new' and 'menu'
        my @trim = @unis.grep({ ! /^ Method\+\{is\-nodal\}\.new /
}).grep({ ! / ^ (menu) \s* $ / });
    }
}

01-method-menu.t:

use v6;
use Test;
use method-menu;
my $test_case = "'use method-menu;' and the 'm' method";
subtest {
  my $report1 = (Array).m;
  my @report1 = $report1.lines;
  my $l1 = @report1.elems;  # 203
  cmp-ok($l1, '>', 24, "report1 shows over 24 methods: $l1");
}, $test_case;
done-testing();
0
doomvox
10/30/2018 2:36:30 AM
perl.perl6.users 1103 articles. 0 followers. Follow

1 Replies
21 Views

Similar Articles

[PageSpeed] 33

--0000000000000d2f5e0579692fc2
Content-Type: text/plain; charset="UTF-8"

What jumps out to me is the difference between a normal method and a
metamethod; the latter might not do sufficient validation, so you're
catching the exception from trying to invoke .gist. And that just happens
to do the right thing in your case; if you're getting a VMNull from an
implementation-internal name (possibly something in NQP which leads to a
VMNull if you try to treat it as a P6 object), that would be likely.

On Mon, Oct 29, 2018 at 10:37 PM Joseph Brenner <doomvox@gmail.com> wrote:

> I've got a weird one here... a line that looks like it does
> nothing significant is needed for the code to work.
> If the line below marked "The Mystery Line" is commented out,
> you just get the error:
>
>    ===SORRY!===
>    Cannot look up attributes in a VMNull type object
>
> Augment::Util:
>
> class Recomposer {
>     method recompose_core {
>         my @type_symbols = (|CORE::).grep({ .key eq .value.^name
> }).map( *.value );
>         for @type_symbols -> $type_symbol {
>             my $type_symbol_name = $type_symbol.^name;
>             try {
>                 my $nada = $type_symbol.gist;  # The Mystery Line
>                 $type_symbol.^compose;
>                 # if there's no ^.compose method, just skip to next
> type symbol object
>                 CATCH {
>                     default { }
>                 }
>             }
>         }
>     }
> }
>
>
> The problem seems to be local to that "recompose_core" routine,
> though just to be complete I'll tack on the rest of my code...
> sorry about the length, it's hard to strip it down much further
> than this.
>
> The goal here is to be able to start the repl with the command:
>
>   perl6 -Mmethod-menu
>
> And have a new method (something like .^methods) named simply .m
> available everywhere.
>
>
> method-menu:
>
> use Object::Examine;
> use Augment::Util;
> use MONKEY-TYPING;
> augment class Any does Introspector {
>     method m {
>         return self.menu;
>     }
>     Recomposer.recompose_core();
> }
>
>
> Object::Examine:
>
> role Introspector {
>     method menu {
>         my @seen_methods = ();
>         my @levels  = self.^mro; # better than ^parents: current class and
> above
>         my $report = '';
>         my @data;
>         for @levels -> $l {
>             my $level_name     = $l.^name;
>             my @current_methods  = clean_methods( methods_for( $l ) );
>             my @child_methods = ( @current_methods (-) @seen_methods
> ).keys;
>             # saving up the data...
>             for @child_methods -> $cm {
>                 @data.push([$cm, $level_name]);
>             }
>             @seen_methods = ( @seen_methods (+) @current_methods ).keys;
>         }
>         my @lines = @data.sort({ $_[0] });
>         for @lines -> $l {
>             my $fmt = "%-25s %-25s\n";
>             $report ~= sprintf $fmt, $l[0], $l[1];
>         }
>         return $report;
>     }
>     sub methods_for(Mu $obj) {
>         my @raws = $obj.^methods(:local);  # or :all?
>     }
>     sub clean_methods (@raws) {
>         my @strs = @raws.map({ .gist });
>         my @ways = @strs.sort;
>         my @unis = @ways.unique;
>         # filter out methods 'Method+{is-nodal}.new' and 'menu'
>         my @trim = @unis.grep({ ! /^ Method\+\{is\-nodal\}\.new /
> }).grep({ ! / ^ (menu) \s* $ / });
>     }
> }
>
> 01-method-menu.t:
>
> use v6;
> use Test;
> use method-menu;
> my $test_case = "'use method-menu;' and the 'm' method";
> subtest {
>   my $report1 = (Array).m;
>   my @report1 = $report1.lines;
>   my $l1 = @report1.elems;  # 203
>   cmp-ok($l1, '>', 24, "report1 shows over 24 methods: $l1");
> }, $test_case;
> done-testing();
>


-- 
brandon s allbery kf8nh
allbery.b@gmail.com

--0000000000000d2f5e0579692fc2
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">What jumps out to me is the difference between a normal me=
thod and a metamethod; the latter might not do sufficient validation, so yo=
u&#39;re catching the exception from trying to invoke .gist. And that just =
happens to do the right thing in your case; if you&#39;re getting a VMNull =
from an implementation-internal name (possibly something in NQP which leads=
 to a VMNull if you try to treat it as a P6 object), that would be likely.<=
/div><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Mon, Oct 29, 2018 a=
t 10:37 PM Joseph Brenner &lt;<a href=3D"mailto:doomvox@gmail.com">doomvox@=
gmail.com</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I&#39;ve=
 got a weird one here... a line that looks like it does<br>
nothing significant is needed for the code to work.<br>
If the line below marked &quot;The Mystery Line&quot; is commented out,<br>
you just get the error:<br>
<br>
=C2=A0 =C2=A0=3D=3D=3DSORRY!=3D=3D=3D<br>
=C2=A0 =C2=A0Cannot look up attributes in a VMNull type object<br>
<br>
Augment::Util:<br>
<br>
class Recomposer {<br>
=C2=A0 =C2=A0 method recompose_core {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @type_symbols =3D (|CORE::).grep({ .key eq .=
value.^name<br>
}).map( *.value );<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for @type_symbols -&gt; $type_symbol {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my $type_symbol_name =3D $type_sy=
mbol.^name;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 try {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my $nada =3D $type_=
symbol.gist;=C2=A0 # The Mystery Line<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $type_symbol.^compo=
se;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 # if there&#39;s no=
 ^.compose method, just skip to next<br>
type symbol object<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CATCH {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 defau=
lt { }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 }<br>
}<br>
<br>
<br>
The problem seems to be local to that &quot;recompose_core&quot; routine,<b=
r>
though just to be complete I&#39;ll tack on the rest of my code...<br>
sorry about the length, it&#39;s hard to strip it down much further<br>
than this.<br>
<br>
The goal here is to be able to start the repl with the command:<br>
<br>
=C2=A0 perl6 -Mmethod-menu<br>
<br>
And have a new method (something like .^methods) named simply .m<br>
available everywhere.<br>
<br>
<br>
method-menu:<br>
<br>
use Object::Examine;<br>
use Augment::Util;<br>
use MONKEY-TYPING;<br>
augment class Any does Introspector {<br>
=C2=A0 =C2=A0 method m {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return self.menu;<br>
=C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 Recomposer.recompose_core();<br>
}<br>
<br>
<br>
Object::Examine:<br>
<br>
role Introspector {<br>
=C2=A0 =C2=A0 method menu {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @seen_methods =3D ();<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @levels=C2=A0 =3D self.^mro; # better than ^=
parents: current class and above<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my $report =3D &#39;&#39;;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @data;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for @levels -&gt; $l {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my $level_name=C2=A0 =C2=A0 =C2=
=A0=3D $l.^name;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my @current_methods=C2=A0 =3D cle=
an_methods( methods_for( $l ) );<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my @child_methods =3D ( @current_=
methods (-) @seen_methods ).keys;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 # saving up the data...<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for @child_methods -&gt; $cm {<br=
>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 @data.push([$cm, $l=
evel_name]);<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 @seen_methods =3D ( @seen_methods=
 (+) @current_methods ).keys;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @lines =3D @data.sort({ $_[0] });<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for @lines -&gt; $l {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my $fmt =3D &quot;%-25s %-25s\n&q=
uot;;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $report ~=3D sprintf $fmt, $l[0],=
 $l[1];<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return $report;<br>
=C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 sub methods_for(Mu $obj) {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @raws =3D $obj.^methods(:local);=C2=A0 # or =
:all?<br>
=C2=A0 =C2=A0 }<br>
=C2=A0 =C2=A0 sub clean_methods (@raws) {<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @strs =3D @raws.map({ .gist });<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @ways =3D @strs.sort;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @unis =3D @ways.unique;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 # filter out methods &#39;Method+{is-nodal}.new=
&#39; and &#39;menu&#39;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 my @trim =3D @unis.grep({ ! /^ Method\+\{is\-no=
dal\}\.new /<br>
}).grep({ ! / ^ (menu) \s* $ / });<br>
=C2=A0 =C2=A0 }<br>
}<br>
<br>
01-method-menu.t:<br>
<br>
use v6;<br>
use Test;<br>
use method-menu;<br>
my $test_case =3D &quot;&#39;use method-menu;&#39; and the &#39;m&#39; meth=
od&quot;;<br>
subtest {<br>
=C2=A0 my $report1 =3D (Array).m;<br>
=C2=A0 my @report1 =3D $report1.lines;<br>
=C2=A0 my $l1 =3D @report1.elems;=C2=A0 # 203<br>
=C2=A0 cmp-ok($l1, &#39;&gt;&#39;, 24, &quot;report1 shows over 24 methods:=
 $l1&quot;);<br>
}, $test_case;<br>
done-testing();<br>
</blockquote></div><br clear=3D"all"><div><br></div>-- <br><div dir=3D"ltr"=
 class=3D"gmail_signature" data-smartmail=3D"gmail_signature"><div dir=3D"l=
tr"><div><div dir=3D"ltr"><div>brandon s allbery kf8nh</div><div><a href=3D=
"mailto:allbery.b@gmail.com" target=3D"_blank">allbery.b@gmail.com</a></div=
></div></div></div></div>

--0000000000000d2f5e0579692fc2--
0
allbery
10/30/2018 2:45:40 AM
Reply: