Another bit of a questioning brain dump, which topically follows my post of August 30th titled "derived class generators and introspection", since I'm having trouble sleeping at the moment, with it on my mind ...

Any answers would be appreciated.

I would like to know, first of all, if we anonymously declare 2 specialized classes that happen to be the same, does Perl treat them as the same.

Take this situation:

  my Array of Int $foo;
  my Array of Int $bar;
  my Array of Str $baz;
  $foo.WHAT eqv $bar.WHAT; # true or false?
  $foo.WHAT eqv $baz.WHAT; # true or false?

I don't know if eqv will do what I want in this case, or whether I need to use something else, but I would like a terse generic test that returns true for the first comparison and false for the second.

The test should also work for any such arbitrary 2 specialized class definitions, regardless of their dimensionality and regardless of what they are composed of, be it Array, Hash, Set, Mapping, Seq, Pair, Signature, Capture, etc.

I would also like to know if the collection of a class' attributes is the same as a Signature or not, since they look rather similar to me. If it is not a Signature, then what is the name of the data type that represents just the collection of attributes that a class has? Similarly, what is the name of the data type that represents a single attribute definition, or of a single element of a Signature?

In a similar fashion, I would like an easy way to use a class' collection of attributes like a uniquely identifying fingerprint, and use that to generate the name of that class or use it in its place.

Within certain limits that can be otherwise specified, such as for those that subclass a certain other class (let's call it Tuple), I would like for class definitions to be like singletons, such that no 2 classes can have the same collection of attributes, and if one tries to define a class with the same attributes twice, the second attempt just returns the existing class from the first attempt rather than making a new one.

Perhaps the problem can be simplified in a fashion by leveraging the feature where you can declare a symbolic alias for a class, so that the same class definition can be known by multiple names, but they are treated as the same.

For one example:

  class Foo is Tuple {
    has Str $.name;
    has Int $.age;
  }

  class Bar is Tuple {
    has Str $.name;
    has Int $.age;
  }

  class Baz is Tuple {
    has Str $.name;
    has Int $.age;
    has Bool $.is_alive;
  }

  $a.WHAT =:= $b.WHAT; # true
  $a.WHAT =:= $c.WHAT; # false

  my Foo $a = Foo.new(...); # successful
  my Foo $b = Bar.new(...); # successful
  my Foo $c = Baz.new(...); # compile or runtime exception

In the above example, I want to be able to declare Tuple in such a way that it would cause the above behaviour implicitly, eg that Bar ::= Foo without the user who declares Foo or Bar doing the ::= explicitly.

But this needs to work for both explicitly and implicitly defined classes. For example, continuing from the above:

  my Baz $d = Baz.new(...); # successful
  my Foo $e = $d.project( 'name', 'age' ); # successful
  $e === Foo.new( name => $d.name, age => $d.age ); # true

  class Quux is Tuple {
    has Bool $is_alive;
  }

  my Quux $f = Quux.new(...); # successful
  my Baz $g = $a.join( $f ); # successful

  class Fuz is Tuple {
    has Int $.is_alive;
  }

  class Fizz is Tuple {
    has Bool $.is_dead;
  }

  my Quux $h = Fuz.new(...); # fails
  my Quux $i = Fizz.new(...); # fails
  my Baz $j = $a.join( $h ); # fails

Now, maybe I can accomplish what I want in some submethod or other of Tuple, which has access to the pseudo meta-class or whatever of the class being created around it, but I would appreciate some helpful code examples for exactly how to accomplish this.

I would also appreciate examples of how to generate a class or classless object period at runtime using the meta-model, since the above project() and join() methods above would be doing just that.

(Now, the reason that I didn't use Tuple with 'does' rather than 'is' is that I wanted to keep separate 2 classes that do Tuple but are implemented differently, such as in-RAM-only vs tied-to-disk-file; they would say "is TupleInRAM" or "is TupleOnDisk" respectively, and even if a class of one declares the same attributes as the other, they would be treated as 2 distinct classes by Perl; while they could be used interchangeably in some situations, certain other situations would make that unwise. That said, practically speaking, "does" *may* be better than "is" for what I'm suggesting, or it may not, but either way I would like to have something like the above behaviour.)

Oh yes, while I didn't include it in the above examples, any class that is/does Tuple should be able to be an attribute type of another one. For example:

  class Pouf is Tuple {
    has Foo $.foo;
    has Quux $.z;
    has Str $.str;
  }

  class Perf is Tuple {
    has Bar $.foo;
    has Quux $.z;
    has Str $.str;
  }

  class Putz is Tuple {
    has Foo $.foo;
    has Fuz $.z;
    has Str $.str;
  }

  Pouf.WHAT =:= Perf.WHAT; # true
  Pouf.WHAT =:= Putz.WHAT; # false

A key thing is, generally or specific to an implementation, a Tuple's class name doesn't matter, but just what its attribute names and types are what matter.

Thank you for any feedback and help. A proper Perl-saavy Set::Relation implementation is much closer to reality if I can get these issues solved and implemented in practice.

-- Darren Duncan

Reply via email to