develooper Front page | perl.perl6.language | Postings from March 2005

Re: some misc Perl 6 questions

Thread Previous | Thread Next
Larry Wall
March 8, 2005 17:35
Re: some misc Perl 6 questions
Message ID:
On Tue, Mar 08, 2005 at 03:50:41PM -0800, Darren Duncan wrote:
: Greetings,
: I have just started to write a large amount of Perl 6 code, partly to 
: help with testing the Pugs (and later Parrot) implementation of the 
: language.  During this process, I discovered a few details about Perl 
: 6 that I don't yet understand, and haven't yet been able to get 
: answers to in my reading of the Synopsis.  So I'll ask about them 
: here.
: For some of these points, I just wanted clarification on something I 
: think I already know, and for others its just a "how do I" matter:
: 0. As I understand it, the current state of being says that all Perl 
: 6 code will by default "use strict" and "use warnings" (y/n), unless 
: it's a one-liner?


: 1. What is the behaviour of require() in regards to what it does when 
: a module or class was previously defined in a file that was already 
: loaded, but that file didn't have a file name that corresponded to 
: the module or class?  Eg, say a program determines at runtime that it 
: wants to use module Foo, and that module is defined in a file named 
: Bar that declares both the Bar and the Foo module.  If the program 
: had already loaded file Bar sometime earlier, then will "require Foo" 
: use the existing declaration, or try to load a file named "Foo" but 
: fail?  Or will something else happen.  Essentially, I want users of 
: my module to be able to declare a data-containing module using either 
: method, its own file or shared in another file, and my module to just 
: see and use it.
: For reference, this is what I currently have to do in Perl 5:
:   no strict 'refs';
:   my $package_is_loaded = defined %{$template_module_name~'::'};
:   use strict 'refs';
:   unless( $package_is_loaded ) {
:     require $template_module_name;
:   }
:   $text = $template_module_name->get_text_by_key( $message.msg_key );
: I do that because Perl 5 require() always attempts to load a matching 
: file name.

I think Perl 6 will probably try to do the same.  I suspect it's better
to keep the require/use interface as a simple mapping to filename
space, and let you provide a different interface that documents that
you're doing something non-standard, rather than complicating the
standard interface.

Of course, I speak with forked tongue here, because we're already
complicating the whole module system with the shortname/longname
distinction in order to get control of versioning, so there probably
has to be a database somewhere of mappings of each short name to all
corresponding long names, and for each of those, to their compilation
state and actual location.  You could in principle subvert that
mechanism.  But I still think it'd be a mistake, unless we can make
it fall out of the design naturally.

: 2. Related to the above, if the require() of Perl 6 will indeed try 
: to load a file with the matching name, then what is the proper way to 
: test if a module was already loaded?  Hopefully this is elegant, 
: rather than the Perl 5 "no strict 'refs'" cludge.  ('cludge' means 
: anything I need to un-strict to accomplish.)

There is no need for "strict refs" in Perl 6, since we distinguish
symbolic naming from referential naming syntactically in most cases.

But as for whether a module is loaded or not, what do you mean by
"module"?  I think the interface should allow you to ask, "If I
did this particular use or require, what would it actually do."
Part of the return information on that would be not only whether
it would load a file, but which version of the file would be loaded
(or is already loaded), if you've wildcarded the version and/or author.

: 3. Does my explicit new() method get a "$self:" argument that is 
: already instantiated like other methods, or do I have to do something 
: like a bless() on my own declared variable of the class type and 
: explicitly return that?

Er, the invocant on a constructor is generally not $self, but $class.
But anything that is declared "method" rather than "sub" gets an implicit
invocant if the first arg doesn't end with ':'.

You do have to do a $class.bless(%args) at some point in the constructor.
A12 discusses this.  (Note there are Updates since the syntax has changed
over time.)  The new $self is not mentioned as an argument, just returned,
at least for objects of the standard opaque class.  Objects emulating
Perl 5 hashes and such can specify an input hash to bless--the details
are delegated to the CREATE and BUILD submethods, which .bless calls

: 4. Is it possible to create a 'class' that sub-classes a 'module' or 
: can one only subclass a 'class'.  The reason I'm declaring the parent 
: as a module is because it doesn't have any attributes, but it does 
: have utility functions that I wish for users of multiple sub-classes 
: to be able to invoke off of them.

That sounds more like a role than a class or module.  You can compose
a role into a class and its methods may be inherited by subclasses.
It's probably illegal to declare a method in an ordinary module, however.

: 5. If I have a class property defined using "has Str;", and an 
: object of the class is named "$bar", then is it correct syntax to 
: refer to the property as a whole using "$" and an element 
: using "${'abc'}"?

Yes, except that "has" always declares instance attributes, not class
attributes.  You'd want "our" or "my" instead.  But as long as you
declare the name with, it'll generate the accessor.  However,
it might be wiser to go ahead and wrap your own accessor around it
that takes the subscripting out of the hands of the user, in case
you want to change the representation from hash to something else.
(Though, of course, you can always return a tied hash that proxies
for the real data.  But sometimes it's better not to box yourself
into that corner.  In particular, with a method interface you can
add in options, which would be harder with a hash interface--you'd
have to emulate a multi-dimensional hash to get extra "keys" in.)

: 6. I understand that sub/method arguments are passed in read-only by 
: default.  However, if (see #2) I do a "return( $ );" when will 
: the caller getting that return value have received a reference to or 
: a copy of the attribute?

Reference.  If you pass a reference out of your method, even if the
method itself is not rw, you're letting the user do whatever they
want through the reference.  To do otherwise sends us down the tunnel
of C++ const madness.

: 7. Say I have 2 arrays of arrays, @foo and @bar.  What is the most 
: concise Perl 6 syntax for each of these operations in Perl 5?  The 
: Perl 5 equivalent is expressed where each is an array having array 
: refs that are unalike in size.
:   @foo = @bar  # a shallow copy
:   @foo = map { [@{$_}] } @bar  # a deep copy

Works the same in Perl 6, if you've got arrays of arrays.  But if
you're just trying to do two-dimension arrays, then you can use
something like shape(Inf,Inf) to effectively bring the second dimension
up to the status of the first dimension, in which case

    @foo = @bar

would do the deep copy, or more accurately, the shallow copy includes
the second dimension.  See S9 for info about shape().  Note that a
two dimensional array would be subscripted @foo[1;2] rather than 

: 8. Is it possible with a sub or method argument signiture to specify 
: that the arguments must have defined values?  Or are specced 
: non-optional arguments only guaranteed to have the correct container 
: passed to them?

I think you can place that constraint on a formal parameter with

    $arg of Any where { .defined }

or some such.  The MMD engine will simply ignore that particular
signature if the constraint isn't satisfied.

: 9. What does the as() method on built-in types do on a hash that has 
: undefined values?  Does it raise a "use of undefined value in string" 
: warning, or just substitute the empty string?

Warnings are on by default, so I expect you get a warning and it substitutes
the empty string, just like Perl 5.  We still trying to be failsoft here.

: 10. When using as(), can I specify that the results get sorted?  Or 
: alternately, will hashes always serialize in the same order on all 
: platforms, unlike in Perl 5 where its pairs come out in an apparently 
: random order?  If not, I will have to continue to do manually what 
: as() does.

The default will probably be random, but whether there's an easy switch
to sort it, or we rely on a subsequent .sort, depends on how we define
sort to work on things like lists of pairs, I suppose, and whether .as
is return a list of pairs or just alternating keys and values like .kv.
And that probably depends on what you're converting to, which is context
dependant.  Just saying "as" is not enough information to decide.  You
have to specify "as what".

: Okay, that's it for my initial set of questions.
: Thanks in advance for any feedback, whether they are plain answers or 
: pointers to where *exactly* in the Perl 6 spec I should successfully 
: find the answer.

Hope this helps.  Thanks for your efforts.  We're gonna get there, folks!


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About