Thanks for your feedback Larry; much appreciated it is.

A few more interesting things happened since then, which can be seen in the current version of Locale::KeyedText in the Pugs version control.

At 5:35 PM -0800 3/8/05, Larry Wall wrote:
: 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.

The biggest change is that, upon a re-reading Synopsis 12 (and 9) that was inspired by your above comment, I created some subtypes which I now use everywhere; the declarations and some examples of use are:


  subtype KeyName of Str where { $_.defined and $_ ne '' and $_ !~ m/\W/ }

subtype KeyNameHash of Hash is shape(KeyName) of Str; # keys are of type KeyName, values of type Str

subtype PkgName of Str where { $_.defined and $_ ne '' and $_ !~ m/<-[a-zA-Z0-9_:]>/ }

  subtype PkgNameArray of Array of PkgName;

...

  class Locale::KeyedText::Message {

has KeyName $.msg_key; # str - the machine-readable key that uniquely identifies this message

has KeyNameHash %.msg_vars; # hash (str,str) - named variables for messages, if any, go here

method new( $class: KeyName $msg_key, KeyNameHash ?%msg_vars ) returns Locale::KeyedText::Message {
my $message = $class.bless( {} );
$message.msg_key = $msg_key;
$message.msg_vars = %msg_vars; # copy list values
return( $message );
}


...

  class Locale::KeyedText::Translator {

has PkgNameArray @.tmpl_set_nms; # array of str - list of Template module Set Names to search

has PkgNameArray @.tmpl_mem_nms; # array of str - list of Template module Member Names to search

method new( $class: PkgNameArray @set_names, PkgNameArray @member_names ) returns Locale::KeyedText::Translator {
my $translator = $class.bless( {} );
$translator.tmpl_set_nms = @set_names; # copy list values
$translator.tmpl_mem_nms = @member_names; # copy list values
return( $translator );
}


...

By using subtypes in this way, I could remove a lot of explicit input checking code from my methods, which is great. Also, the "where clause" is not being repeated for every argument or attribute or variable declaration. (I like SQL domains for the same reasons.)

So how does that code sample look? Anything that looks like invalid Perl 6. Anything no one thought of doing before but that looks like a good idea?

A question: Would "has PkgNameArray @.tmpl_set_nms;" do what I expect, where the array as a whole is the sub-type, or would it make an array where each element is the sub-type?

: 5. If I have a class property defined using "has Str %.foo;", and an
: object of the class is named "$bar", then is it correct syntax to
: refer to the property as a whole using "$bar.foo" and an element
: using "$bar.foo{'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 %.foo, 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.

I meant to say "attributes", sorry.

I have my own accessors, with different names, and don't expect anyone to use the autogenerated ones. But I
made the attributes public for now so that one of my classes could access the attributes of one of my other ones directly; both of these are defined in the same file.


Maybe that's a bad idea, and if so I can change it.

New question: Is there a way to say that two classes have a privileged relationship, sort of like a marriage, such that each can see and/or change otherwise private attributes in objects of the other class, and yet the attribute list of each class is completely different from the other? Neither of the two objects is a subclass of the other, nor fulfills a role defined by the other.

For example, say that there are two closely related classes, Container and Node, where conceptually a Container object is an environment in which Node objects live. I would like to declare the attributes of both classes private from the viewpoint of all other classes, but I want Container and Node objects to be able to read or set each others' attributes directly as if they were public. Both classes have their own set of methods that outside code can invoke directly, and each kind of object can be held by external code.

Also, does my request sound like something that would be reasonable to do, or a bad practice to avoid?

Thank you for all the hard work you have been doing.

-- Darren Duncan

Reply via email to