Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Package-qualified names. Differences (if any) between Package::<&var> vs &Package::var?

Tags:

package

raku

Reading through https://docs.perl6.org/language/packages#Package-qualified_names it outlines qualifying package variables with this syntax:

Foo::Bar::<$quux>; #..as an alternative to Foo::Bar::quux;

For reference the package structure used as the example in the document is:

class Foo {
    sub zape () { say "zipi" }
    class Bar {
        method baz () { return 'Þor is mighty' }
        our &zape = { "zipi" };   #this is the variable I want to resolve
        our $quux = 42;
    }
}

The same page states this style of qualification doesn't work to access &zape in the Foo::Bar package listed above:

(This does not work with the &zape variable)

Yet, if I try:

Foo::Bar::<&zape>;  # instead of   &Foo::Bar::zape;

it is resolves just fine.

Have I misinterpreted the document or completely missed the point being made? What would be the logic behind it 'not working' with code reference variables vs a scalar for example?

like image 211
drclaw Avatar asked Jun 10 '19 10:06

drclaw


People also ask

Can two classes in the same package have the same name?

Still, the compiler allows both classes to have the same name if they are in different packages. The fully qualified name of each Rectangle class includes the package name.

What is the difference between a package and a class?

Every class is part of some package. If no package is specified, the classes in the file goes into a special unnamed package (the same unnamed package for all files). All classes/interfaces in a file are part of the same package. Multiple files can specify the same package name.

What happens if no package is specified in a file?

If no package is specified, the classes in the file goes into a special unnamed package (the same unnamed package for all files). All classes/interfaces in a file are part of the same package. Multiple files can specify the same package name.

What is a package name in C++?

The package name is closely associated with the directory structure used to store the classes. The classes (and other entities) belonging to a specific package are stored together in the same directory. Furthermore, they are stored in a sub-directory structure specified by its package name.


2 Answers

I'm not aware of differences, but Foo::Bar::<&zape> can also be modified to use {} instead of <>, which then can be used with something other than literals, like this:

my $name = '&zape';
Foo::Bar::{$name}()

or

my $name = 'zape';
&Foo::Bar::{$name}()
like image 146
moritz Avatar answered Sep 24 '22 14:09

moritz


JJ and Moritz have provided useful answers.

This nanswer is a whole nother ball of wax. I've written and discarded several nanswers to your question over the last few days. None have been very useful. I'm not sure this is either but I've decided I've finally got a first version of something worth publishing, regardless of its current usefulness.

In this first installment my nanswer is just a series of observations and questions. I also hope to add an explanation of my observations based on what I glean from spelunking the compiler's code to understand what we see. (For now I've just written up the start of that process as the second half of this nanswer.)

Differences (if any) between Package::<&var> vs &Package::var?

They're fundamentally different syntax. They're not fully interchangeable in where you can write them. They result in different evaluations. Their result can be different things.

Let's step thru lots of variations drawing out the differences.

say Package::<&var>; # compile-time error: Undeclared name: Package

So, forget the ::<...> bit for a moment. P6 is looking at that Package bit and demanding that it be an already declared name. That seems simple enough.

say &Package::var; # (Any)

Quite a difference! For some reason, for this second syntax, P6 has no problem with those two arbitrary names (Package and var) not having been declared. Who knows what it's doing with the &. And why is it (Any) and not (Callable) or Nil?

Let's try declaring these things. First:

my Package::<&var> = { 42 } # compile-time error: Type 'Package' is not declared

OK. But if we declare Package things don't really improve:

package Package {}
my Package::<&var> = { 42 } # compile-time error: Malformed my

OK, start with a clean slate again, without the package declaration. What about the other syntax?:

my &Package::var = { 42 }

Yay. P6 accepts this code. Now, for the next few lines we'll assume the declaration above. What about:

say &Package::var(); # 42

\o/ So can we use the other syntax?:

say Package::<&var>(); # compile-time error: Undeclared name: Package

Nope. It seems like the my didn't declare a Package with a &var in it. Maybe it declared a &Package::var, where the :: just happens to be part of the name but isn't about packages? P6 supports a bunch of "pseudo" packages. One of them is LEXICAL:

say LEXICAL::; # PseudoStash.new(... &Package::var => (Callable) ... 

Bingo. Or is it?

say LEXICAL::<&Package::var>(); # Cannot invoke this object
                                # (REPR: Uninstantiable; Callable)

What happened to our { 42 }?

Hmm. Let's start from a clean slate and create &Package::var in a completely different way:

package Package { our sub var { 99 } }
say &Package::var();   # 99
say Package::<&var>(); # 99

Wow. Now, assuming those lines above and trying to add more:

my Package::<&var> = { 42 } # Compile-time error: Malformed my

That was to be expected given our previous attempt above. What about:

my &Package::var = { 42 }   # Cannot modify an immutable Sub (&var)

Is it all making sense now? ;)

Spelunking the compiler code, checking the grammar

1 I spent a long time trying to work out what the deal really is before looking at the source code of the Rakudo compiler. This is a footnote covering my initial compiler spelunking. I hope to continue it tomorrow and turn this nanswer into an answer this weekend.

The good news is it's just P6 code -- most of Rakudo is written in P6.

The bad news is knowing where to look. You might see the doc directory and then the compiler overview. But then you'll notice the overview doc has barely been touched since 2010! Don't bother. Perhaps Andrew Shitov's "internals" posts will help orient you? Moving on...

In this case what I am interested in is understanding the precise nature of the Package::<&var> and &Package::var forms of syntax. When I type "syntax" into GH's repo search field the second file listed is the Perl 6 Grammar. Bingo.

Now comes the ugly news. The Perl 6 Grammar file is 6K LOC and looks super intimidating. But I find it all makes sense when I keep my cool.

Next, I'm wondering what to search for on the page. :: nets 600+ matches. Hmm. ::< is just 1, but it is in an error message. But in what? In token morename. Looking at that I can see it's likely not relevant. But the '::' near the start of the token is just the ticket. Searching the page for '::' yields 10 matches. The first 4 (from the start of the file) are more error messages. The next two are in the above morename token. 4 matches left.

The next one appears a quarter way thru token term:sym<name>. A "name". .oO ( Undeclared name: Package So maybe this is relevant? )

Next, token typename. A "typename". .oO ( Type 'Package' is not declared So maybe this is relevant too? )

token methodop. Definitely not relevant.

Finally token infix:sym<?? !!>. Nope.

like image 26
raiph Avatar answered Sep 24 '22 14:09

raiph