Re: Roles and Trust

2005-10-12 Thread Piers Cawley
Ovid <[EMAIL PROTECTED]> writes:

> --- Piers Cawley <[EMAIL PROTECTED]> wrote:
>> 
>> How about:
>> 
>>   my method SCALAR::attributes($self:) { $$self }
>>   my method HASH::attributes(%self:) { %self.kv }
>>   my method ARRAY::attributes(@self:) { [EMAIL PROTECTED] }
>> 
>>   method _attributes($attrs) {
>> my @attributes = $attrs.attributes
>> return @attributes[0] if @attributes == 1;
>> ...
>>   }
>> 
>> Assuming it's legal.
>
> Just saw this.  Sorry for the late reply.
>
> At first that gave me the willies, then I noticed the "my" on the
> front.  I assume because of the "my" on there that this would affect
> those data types only locally?  That seems like it would be a nice
> compromise.
>
> Is this legal syntax?

After some discussion on #perl6, we thought probably not (unless
@Larry rules otherwise). However, 

  my multi attributes( Scalar $scalar: ) { $$scalar }
  my multi attributes( Hash %hash: ) { %hash.kv }
  my multi attributes( Array @array: )   { [EMAIL PROTECTED]  }

definitely is legal (though it does rather suffer from the end-weight
problem to my way of thinking).

-- 
Piers Cawley <[EMAIL PROTECTED]>
http://www.bofh.org.uk/


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Brent,

On Oct 11, 2005, at 8:17 PM, Brent 'Dax' Royal-Gordon wrote:

Stevan Little <[EMAIL PROTECTED]> wrote:


I would like to propose that class methods do not get inherited along
normal class lines.



I think you're not thinking about many major usage cases for class  
methods.


Actually I have considered many common usages including those which  
you describe below, and it is my belief that only a few are truly  
valid uses and not abuses of class method functionality. What I kept  
coming back to was that pretty much all the *abuses* of class methods  
were better done in some other way, and that even the *valid* uses  
were nothing more than design choices, and could be accomplished in  
some other manner.



For one example, look at my Cipher suite.  (It's in Pugs's ext/Cipher
directory.)  The Cipher base class implements most of the visible API,
while subclasses simply override a few internal methods; Cipher turns
the wide-ranging, convenient external API into a smaller, more easily
implementable internal API.


Your internal API and your external API have little to do with one  
another as far as I can tell. The external API is simply a set of  
convenience functions which create instances of your classes in  
various ways (very cool ways I might add, especially the functional  
API, very nice stuff). However, you could easily remove external API,  
and your internal API would not really suffer, it would only require  
that the user manually create what your class methods create for you.


While many people think Factories are many times overkill (me among  
them), what you are doing is a perfect candidate for the Factory  
pattern. In fact, one could say you are already doing an ad-hoc  
Factory pattern with your inheritable class methods.



Some of Cipher's methods are class methods, including the
pseudo-procedural .encipher/.decipher and the pseudo-functional
.encipherer/.decipherer methods.  These methods are included
specifically *to* be inherited.


Your documentation says the following things:

  The Cipher API's procedural interface is good enough for many  
purposes.
  Although the interface is said to be procedural, it is invoked via  
two class

  methods.

  The Cipher API is fundamentally object-oriented; the procedural  
and functional

  interfaces are layers on top of the object-oriented backend.

Both indicate to me an acknowledgment that you are knowingly abusing  
the inheritance of class methods to make your functional and  
procedural APIs work. Now, please don't take this as an insult or  
slam of some kind. All good programmers know when to abuse language  
elements to get what they need. However, I am of the opinion that  
maybe we should leave these old idioms/abuses aside.



In my opinion, class method inheritance is an important part of
class-based OO--almost as important as object method inheritance.


I disagree with you on this point (of course, otherwise I would not  
have started this thread), but I will admit that inheritable class  
methods are a very common OO idiom, and that fact (good or bad)  
should be taken into account.



Removing features simply because their implementation is inconvenient
is not The Perl Way.  If it were, Perl 6 would be Java With Sigils.


To be honest, the implementation is not inconvenient at all, in fact  
I have already done it twice (correctly at least, the meta-model  
currently has inheritable class methods, but the implementation is  
crap).


1) A Mini-MetaModel with Eigenclasses

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ 
MiniMetaModel_w_eigenclasses.pl


Whenever I am doing something which has the potential to dig deeply  
into the core of the meta-model, I do it first with a Mini-MetaModel.  
(The MMM (mini-meta-model) is a small self-bootstrapping single- 
inheritance meta-model in under 2-300 LOC and usually which tends to  
be much easier to "mess with" than the real meta-model.) If you look  
at the "new" method in Class, you will see it creates an Eigenclass  
for each class (this is where the class methods get stored), then  
adding class methods is accomplished with the "add_singleton_method"  
method. You will find a number of tests towards the bottom of the  
file which demonstrate the inheritance of the class methods.


2) By using a subclass of Class

http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 
37_inherited_class_methods.t


I did this test at autrijus's request, it creates a  
"ClassWithInheritedClassMethods" class which is a subclass of Class.  
If you create your classes (Foo, Bar, what have you) using  
"ClassWithInheritedClassMethods", then you can add class methods,  
again with the "add_singleton_method", and they are inherited  
correctly by subclasses.


The code to make "ClassWithInheritedClassMethods" work is only 10  
lines long, so as you can see the implementation is not difficult or  
inconvenient at all.


To properly implement this in the current meta-model pr

Re: Proposal to make class method non-inheritable

2005-10-12 Thread Rob Kinyon
All -

I'm partly to blame for this thread because I put the idea into
Steve's head that class methods being inheritable may be dogma and not
a useful thing. Mea culpa.

That said, I want to put forward a possible reason why you would
want class methods to be inheritable - to provide pure functions.

If we go back to every function/method/subroutine being behavior,
it's pretty evident that you need some state for that behavior to
operate upon. In a procedural function, the state is provided. In an
object, that state is both provided and inherent in the instance the
method is operating upon. In functional languages, functions maintain
their own state through closures, continuations,  and the like.

I might want to provide in a base class a set of useful sorting
routines or other such items. These would be true procedural functions
and there would be a warning thrown if it accessed class state.

Rob


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Brent 'Dax' Royal-Gordon
Stevan Little <[EMAIL PROTECTED]> wrote:
> I would like to propose that class methods do not get inherited along
> normal class lines.

I think you're not thinking about many major usage cases for class methods.

For one example, look at my Cipher suite.  (It's in Pugs's ext/Cipher
directory.)  The Cipher base class implements most of the visible API,
while subclasses simply override a few internal methods; Cipher turns
the wide-ranging, convenient external API into a smaller, more easily
implementable internal API.

Some of Cipher's methods are class methods, including the
pseudo-procedural .encipher/.decipher and the pseudo-functional
.encipherer/.decipherer methods.  These methods are included
specifically *to* be inherited.

In my opinion, class method inheritance is an important part of
class-based OO--almost as important as object method inheritance. 
Removing features simply because their implementation is inconvenient
is not The Perl Way.  If it were, Perl 6 would be Java With Sigils.

--
Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]>
Perl and Parrot hacker


Re: multiline comments

2005-10-12 Thread Alfie John


It was just kind of a pain because you
had to put a "=cut" after the "=end", and because you had to put
paragraph spaces between everything.  We're getting rid of both of
those restrictions.


Excellent! That's what was really bugging me. I'm really glad that is  
changing :)


Thanks,
Alfie


Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))

2005-10-12 Thread Luke Palmer
On 10/12/05, Rob Kinyon <[EMAIL PROTECTED]> wrote:
> Plus, I can't imagine that a reverser for Parrot code is going to be that 
> hard to
> write.

Disassembling register machine code is significantly more difficult
than disassembling stack machine code.

That said, if the level of introspective capabilities is high, then
disassembling is probably not hard. As far as I know, keeping
introspective capabilities high is a major Perl goal :-)

> Alternately, maybe you have a pragma that says "Finalize all classes
> unless I specify that it should remain open."

That's the plan, where the pragma is only available before any modules
are loaded, IIRC  (this keeps modules from closing themselves off).

I think this is an opportune time for me to express that I think the
ability to close-source a module is important.  I love open source,
and I couldn't imagine writing anything by myself that I wouldn't
share.  But in order for Perl to be taken seriously as a commercial
client-side language, it must be possible to close the source.  I
started writing a game with a few friends last year, and as we were
picking our implementation strategy, using Perl as the primary
"sequencing engine" for non-time-critical tasks was immediately
discounted when I commented that anybody can look at your perl source
if they want to.

Of course, there is no argument there for allowing closed-source
*modules*, just complete applications.  But I'm sure you could fish
one out involving dynamic loading, or modding, or whatever you want to
call it.

Luke


Re: Complex types

2005-10-12 Thread Autrijus Tang

Larry Wall wrote:

On Thu, Oct 13, 2005 at 09:43:15AM +1300, Sam Vilain wrote:
: Hi all,
: 
: Is it intentional that S09 lists unboxed complex types, but equivalent

: Boxed types are missing from the "Types" section in S06?

Nope.


As it's a trivial omission, I went ahead and changed S06.pod (r6201).

Thanks,
/Autrijus/


Re: Complex types

2005-10-12 Thread Larry Wall
On Thu, Oct 13, 2005 at 09:43:15AM +1300, Sam Vilain wrote:
: Hi all,
: 
: Is it intentional that S09 lists unboxed complex types, but equivalent
: Boxed types are missing from the "Types" section in S06?

Nope.

Larry


Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))

2005-10-12 Thread Rob Kinyon
On 10/12/05, chromatic <[EMAIL PROTECTED]> wrote:
> On Wed, 2005-10-12 at 21:50 +0200, Yuval Kogman wrote:
>
> > This has even more implications with closed classes to which you
> > don't have source level access, and if this can happen it will
> > happen - i'm pretty sure that some commercial database vendors would
> > release closed source DBDs, for example.
>
> Closed classes should not exist.
>
> At least, they should only exist if the person *running* Perl 6 wants
> them to exist -- never if merely the class writer wants to close them.

I'm not sure y'all are talking apples and apples. Yuval is talking
about lack of source-level access and the class being closed. I'm not
quite sure how we end up with a lack of source-level access,
particularly as that locks me, the user of your module, into one
specific P6 interpreter (presumably Parrot). Given the work that
Autrijus and company have been doing with PIL and Pugs in general,
closing the source (presumably by releasing Parrot bytecode) isn't
going to really work. (Plus, I can't imagine that a reverser for
Parrot code is going to be that hard to write.)

Furthermore, is releasing just the Parrot bytecode going to work in
multi-lingual apps? Aren't there optimizations that may not be
appropriate before all the languages are known? (I'm completely out on
a limb, here.)

That said, I agree with chromatic closing (or finalizing) a class
should be the action of the consumer, not the producer. Maybe the
producer could signal his/her desire to close the class when some
phase is finished. That would mean the consumer could either modify
the class before that phase is finished and/or the consumer could
intercept the request for finalization.

Alternately, maybe you have a pragma that says "Finalize all classes
unless I specify that it should remain open." Maybe, we need a
negation for close? keep_open?

Rob


Complex types

2005-10-12 Thread Sam Vilain
Hi all,

Is it intentional that S09 lists unboxed complex types, but equivalent
Boxed types are missing from the "Types" section in S06?

Sam.



Closed Classes Polemic (was Re: What the heck is a submethod (good for))

2005-10-12 Thread chromatic
On Wed, 2005-10-12 at 21:50 +0200, Yuval Kogman wrote:

> This has even more implications with closed classes to which you
> don't have source level access, and if this can happen it will
> happen - i'm pretty sure that some commercial database vendors would
> release closed source DBDs, for example.

Closed classes should not exist.

At least, they should only exist if the person *running* Perl 6 wants
them to exist -- never if merely the class writer wants to close them.

-- c



Re: What the heck is a submethod (good for)

2005-10-12 Thread Yuval Kogman
On Thu, Oct 13, 2005 at 05:42:31 +1000, Damian Conway wrote:
> Luke wrote:
> 
> >Okay, I seriously have to see an example of a submethod in use.
> 
>  class Driver::Qualified {
>  method drive {
>  print "Brrrm brrrm!"
>  }
>  }
> 
>  class Driver::Disqualified is Driver {
>  submethod drive {
>  die .name(), " not allowed to drive"
>  }
>  }
> 
>  class Driver::Requalified is Driver::Disqualified {}

This is not obvious that the behavior is modified, and it makes
other subclasses, like Driver::Disqualified::Drunk and
Driver::Disqualified::Suicidal causes the above design choice to
make you either update Driver::Requalified and Driver::Disqualified
to regular methods, or duplicate code in Driver::Disqualified::*.

That much aside, this is not a real world example. Can you try to
think of one that really applies? Looking at my past $work projects
I can't think of a single instance where submethods would help me
code better. On the other hand roles & mixin inheritence, private
attributes that don't conflict with other private attributes of the
same name, better polymorphism, better introspection, and a
metamodel could have helped a lot in many places.

This has even more implications with closed classes to which you
don't have source level access, and if this can happen it will
happen - i'm pretty sure that some commercial database vendors would
release closed source DBDs, for example.

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: : neeyah!



pgpb15yuOsYCY.pgp
Description: PGP signature


Re: What the heck is a submethod (good for)

2005-10-12 Thread Damian Conway

Luke wrote:


Okay, I seriously have to see an example of a submethod in use.


class Driver::Qualified {
method drive {
print "Brrrm brrrm!"
}
}

class Driver::Disqualified is Driver {
submethod drive {
die .name(), " not allowed to drive"
}
}

class Driver::Requalified is Driver::Disqualified {}

my Driver $preDUI  = Driver::Qualified.new();
my Driver $perDUI  = Driver::Disqualified.new();
my Driver $postDUI = Driver::Requalified.new();

$preDUI.drive();   # calls &Driver::Qualified::drive
$perDUI.drive();   # calls &Driver::Disqualified::drive
$postDUI.drive();  # calls &Driver::Qualified::drive

Damian





Re: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen
Actually, I wondered why you didn't suggest this earlier. :) I  
figured you were a step ahead of me: What if I want more than a  
boolean out of my class method?


On Oct 12, 2005, at 10:27, Stevan Little wrote:


Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it  
"supportsFeatureB", you can just see if it does the "FeatureB"  
role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being  
treated as a role, ABC will actually consume all it's subroles,  
which means that ABC will DWIM too. In fact, we get even more from  
this system since we can check if one plug-in is capable of "doing"  
another, because this "just works"


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working  
code, I coded this up using the current meta-model prototype. You  
can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- 
MetaModel/t/38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a "class method" in it, which
# the consuming class will get as a "class method"
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}








—

Gordon Henriksen
[EMAIL PROTECTED]




What the heck is a submethod (good for)

2005-10-12 Thread Luke Palmer
Okay, I seriously have to see an example of a submethod in use.  BUILD
etc. don't count.  Why?  Because:

class Foo {
method BUILD () { say "foo" }
}
class Bar is Foo {
submethod BUILD () { say "bar" }
}
class Baz is Bar { }

Foo.new;   # foo
Bar.new;   # foo bar
Baz.new;  # foo bar

If the submethod property of BUILD were actually doing anything, then
we should expect it to read like this:

Foo.new;   # foo
Bar.new;   # bar
Baz.new;  # foo

So I don't see how the constructor is a submethod[1].  And I can't
come up with any examples of where I would want to use a submethod. 
Can someone else?

Luke

[1] Yes, yes, I understand that .new is calling BUILDALL, which is
then calling the BUILDs individually.  I'm saying that the fact that
BUILD is a submethod isn't changing anything one bit.


Re: Proposal to make class method non-inheritable

2005-10-12 Thread chromatic
On Wed, 2005-10-12 at 12:00 -0400, Stevan Little wrote:

> Usefulness aside, why do Roles and Classes need to be seperate  
> beasts? In the current meta-model prototype, the role system is laid  
> atop the class system so that the following is true:
> 
> Class is an instance of Class
> Role is an instance of Class
> Class does Role
> 
> This then means that Role also .does Role since Role is an instance  
> of Class (which does Role).
> 
> It gets very cyclical, but it essentially means that all classes can  
> be treated as roles. This allows for all sorts of interesting things  
> to happen actually.

I've always thought that classes were more specific than roles in that
you can't apply a class to another class.  (Maybe that's the wrong
direction of specificity.  Though I am positive that .does() is more
general than .isa(), I always have to stop and think about which
direction co- and contra-variance goes.)

Certainly I think declaring a class should imply a role of the same
name, even if you can't actually apply that role and mix in state and
behavior.

> I have to admit though, that this comes directly from Scala (so maybe  
> we are not alone here out on the edge :)

I've also heard that Sather does something similar but don't know any
details.

-- c



Re: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen

On Oct 12, 2005, at 09:41, Stevan Little wrote:

If you use the BUILD submethod, then you never need to worry about  
a that, everything is initialized for you by BUILDALL. Now, if you  
want to have a constructor which accepts positional arguments  
rather than named pairs (as the default does), then you have a  
valid need to override &new. Whether you should force this upon all  
your subclasses is a matter of opinion I think.


For varying definitions of initialized. I never much cared for the  
bare "poke stuff straight into my instance variables" constructor  
along the lines of:


sub new {
my($class, %ARGS);
return bless \%ARGS, $class;
}

That more or less robs the constructor of the "behavior" part of  
"class = state + behavior." I need an opportunity to establish my  
invariants.


Of course, when there is no such behavior, it saves a lot of  
repetitive typing in the class. C# 3 is finally growing a syntax that  
resolves this by having the language do the repetitive typing at the  
call site...


X x = new X{ Y = 1, Z = 2 };

means

X x = new X();
x.Y = 1;
x.Z = 2;

And X doesn't need anything but the default constructor.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of "class  
methods" very easily.


  Class
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

Now, method dispatch for Bar will go first to it's class (eBar),  
then to any superclasses (eFoo), and any of their superclasses  
(Class), and so on, and so forth. A better diagram of this can be  
found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ 
docs/Method_Dispatch_w_EigenClasses.jpg).


This is more or less how class methods have to work. I would go a bit  
further, though. Too implement this:


Foo : Object
Foo : Bar

The runtime should use an inheritance tree as such:

Object
Class : Object
Foo : Object
Bar : Foo

_Object : Class
_Class : _Object
_Foo : _Class
_Bar : _Foo

Note that every declared class, including Object and Class  
themselves, have an anonymous Class subclass that precisely parallels  
the declared inheritance chain. (Chicken and egg problem? Probably.  
Object and Class are Special.)



With this implementation, there are three places to put state: In  
MyObject (instance variable), in _MyObject (class instance variable),  
or outside of any instance (class variable). The class instance  
variable is the least useful of the three.



Note: I don't see much value in invoking class methods through  
instances, since a Foo IS_NOT_A Class. If one wants to save the user  
typing ".class" when invoking class methods through an instance, I  
would tend toward resolving it as such:


class Foo {
class_method int Bar(int i) { return i * i; }
}

-- BECOMES --

# Common interface for Foo's class methods.
interface _IFoo {
method int Bar(int i);
}

# The anonymous Class.
class _Foo extends Class implements _IFoo {
int Bar(int i) { return i * i; }
}

# The visible class.
class Foo implements _IFoo {
# Forwards the call to the Class.
void Bar(...) { return this.Class.Bar(...); }
}

I'll leave the probably obvious role-based interpretation of this to  
those versed in such. :)



And I'm going to shut my yap, now, having butted into the middle of a  
discussion of a hopelessly complex runtime that I haven't been  
following for a 18 months. :)


—

Gordon Henriksen
[EMAIL PROTECTED]




Re: Sane (less insane) pair semantics

2005-10-12 Thread Ingo Blechschmidt
Hi,

TSa wrote:
> Ingo Blechschmidt wrote:
>> Exactly. I'd like to add that, under the proposal, you always know
>> what things are passed how, only by looking for a "*".
>> 
>> foo $var;# always positionally, even if $var isa Pair
>> foo *$pair;  # always named
> 
> But where is the name? Is it 'pair'? Like in
> 
>foo :pair($pair);

No.

> or dynamically through
> 
>foo $pair.key => $pair.value;

Yep.

> assuming that precedence of => is tighter than foo's.

I think it is.

> As I lengthyly ranted elsewhere in this thread the splat should just
defer the
> structural callability check until runtime. Well, and since everybody
> seems to be happy with .$pair denoting a call through a hardref stored
> in $pair, I don't understand why :$pair is not (yet) denoting a hard
> pairref. Both forms beeing interpreted in the context of the term to

Um, sorry, I don't understand... The only syntax I know of where a $
follows a . is calling method references:

my $meth = method (Foo $self: ...) {...};
$foo.$meth(...);

(But this syntax doesn't have, obviously, anything to do with
magical/non-magical pairs.)

> If full uncertainty isn't your thing, you might instruct the type
> system to make sure that $pair at least doesn't fail you on pairhood
> 
>my Pair $pair;

Yep.

>foo  $pair; # syntactically an item, thus a positional call
>foo *$pair; # guarranteed pair after splatting

>> foo [EMAIL PROTECTED];  # always positionally
> 
> This makes perfect sense to me if you mean that the positionals
> that foo requests are satisfied in the order provided by @array
> without exceptions for pairs, not to mention subtypes of pairs
> or things that do the Pair role etc.

Yep, it's very important that Pairs are not exceptions.

>> foo *%hash;   # always named (hash keys taken as parameter names)
> 
> So that shall fail at compile time if foo has *anonymous* positionals?

Assuming that anonymous positionals exist, yes, I think so.

>> Previously, you wasn't able to know whether you passed something
>> positionally or by name:
>> 
>> sub bar ($x) { grtz $x }
>> bar 42;   # 42 passed to &grtz positionally
>> bar a => 42;  # either the pair (a => 42) passed to &grtz
>>   # positionally or the number 42 passed by name
>> 
>> Under the new proposal, "grtz $x" always passes $x positionally. You
>> don't need &grtz's signature, nor do you need to know $x's type (is
>> $x a Pair?).
> 
> Yep. But you could attempt to dispatch .key on $x in grtz:
> 
> sub grtz ($item)
> {
>say $x.key;
> }
> 
> and get a printout of 'Undef of Key' or so and 'a' respectively.
> HiHi, or a 'method not understood' exception if .key is not applicable
> to 42 ;)

Yep, of course. Pairs are, when not splatted with *, normal instances of
normal classes. (And when pairs are splatted, they are no longer pairs,
but syntactical constructs. (This might of course be implemented using
some class in the compiler, but this is an implementation detail.))

> Stuart Cook wrote:
>>>And look, if you really wanted to, you could define your own
>>>splat-style operator that works exactly as you describe.  But I don't
>>>think it should be the default.
> 
> I think that is difficult *without* parser support because
> a purely prefix thingy doesn't get the coderef the flattened
> array goes to.

Right, also &prefix:<*> can be faked as a normal subroutine (the PIL to
JavaScript compiler does this currently [1]), it has to be some kind of
grammatical rule or perhaps a macro if we want it to be implemented
properly.

>> Right. Under the proposal, you can -- *if you want to* -- use pairs
>> stuffed in arrays as named arguments:
>> 
>> foo *hash(@array_of_pairs);
>>   # @array_of_pairs's pairs used as named args
> 
> This hash function there is hardly the same as the one from S06, that
> takes every other pair from @array_of_pairs, converts *the pair*
> to a key---which might preserve the key actually---and combines it
> with the next entry from the array as value?

Hm. I thought the hash() sub would be a bit more DWIMmy, so it can be
used for desugaring:

my %hash = (a => 1, "b",2, "c");  # desugared to
my %hash = hash(a => 1, "b",2, "c");  # which means
my %hash = (a => 1, b => 2, c => undef);

# thus:
sub hash ([EMAIL PROTECTED]) returns Hash {
my %hash;

while shift @things -> $thing {
given $thing {
when Pair { %hash{$thing.key} = $thing.value }
default {
my $value = shift @things;
%hash{$thing} = $value;
}
}
}

%hash;
}

But, looking at S06, the reference implementation of S06 isn't that
DWIMmy. Dunno whether this is simply a oversight in S06 or whether it
has been purposefully left out.

>@AoP = (a => 'a', b => 'b', c => 'c', d => 'd');
>%hash = hash @AoP;
># = (AoP[0] => AoP[1], AoP[2

Re: Roles and Trust

2005-10-12 Thread Ovid
--- Piers Cawley <[EMAIL PROTECTED]> wrote:
> 
> How about:
> 
>   my method SCALAR::attributes($self:) { $$self }
>   my method HASH::attributes(%self:) { %self.kv }
>   my method ARRAY::attributes(@self:) { [EMAIL PROTECTED] }
> 
>   method _attributes($attrs) {
> my @attributes = $attrs.attributes
> return @attributes[0] if @attributes == 1;
> ...
>   }
> 
> Assuming it's legal.

Just saw this.  Sorry for the late reply.

At first that gave me the willies, then I noticed the "my" on the
front.  I assume because of the "my" on there that this would affect
those data types only locally?  That seems like it would be a nice
compromise.

Is this legal syntax?

Cheers,
Ovid

-- 
If this message is a response to a question on a mailing list, please send
follow up questions to the list.

Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/


Re: Sane (less insane) pair semantics

2005-10-12 Thread TSa

HaloO,

Ingo Blechschmidt wrote:

Exactly. I'd like to add that, under the proposal, you always know what
things are passed how, only by looking for a "*".

foo $var;# always positionally, even if $var isa Pair
foo *$pair;  # always named


But where is the name? Is it 'pair'? Like in

  foo :pair($pair);

or dynamically through

  foo $pair.key => $pair.value;

assuming that precedence of => is tighter than foo's. As I lengthyly ranted
elsewhere in this thread the splat should just defer the structural
callability check until runtime. Well, and since everybody seems to be
happy with .$pair denoting a call through a hardref stored in $pair, I
don't understand why :$pair is not (yet) denoting a hard pairref. Both forms
beeing interpreted in the context of the term to their *immediate* left
which in turn is interpreted leftwards. And both forms fail if the
assumptions about the type of value $pair will eventually refer to
won't hold. The difference to the splat form is eagerness:

  foo :$pair; # eager
  foo *$pair; # lazy

and op versus sigil

  foo  :  $pair;  # syntax error like $ pair
  foo (:  $pair); # same
  foo:$pair;  # labeled statement

  foo  *  $pair;  # infix
  foo (*  $pair); # prefix
 (foo  *) $pair;  # postfix, which I guess doesn't exist


If full uncertainty isn't your thing, you might instruct the type system
to make sure that $pair at least doesn't fail you on pairhood

  my Pair $pair;

  foo  $pair; # syntactically an item, thus a positional call
  foo *$pair; # guarranteed pair after splatting

But of course the call could still fail because there is no parameter
under the key of $pair. Now I think you could instruct the kind type
system also to oversee the meeting of this constraint with

  my Pair of foo $pair;

  foo  $pair; # you guessed it, positional call
  foo *$pair; # always delivers $pair.value into $pair.key
  # parameter of foo

Which might be a too sophisticated variable for your purposes if it
also oversees the values to put into $pair depending on the current
key. This might reduce usability of $pair while you are not calling
foo with it. Thus an intermediate choice could be

  my Pair where .key of foo $pair;
# my $pair is Pair where .key of foo; # same
# my Key of foo $pair; # abbreviation of same?

  foo *$pair; # name hits home, but type error is possible

If you know that all named params of foo are integers you could
oblige yourself to adhere to this with

  my $pair is Pair of Int where .key of foo;

And yes, I know that this should be written

  my $pair is Pair of Int where { .key of foo };

where the ; might be optional. Is it?


The unsigiled foo there is actually shying away from full dynamism:

  &foo *$bar;

This is almost meaningless in itself because it states: "Try to do
what &foo tells you to do with whatever you find in $bar when you try
to do so." But the code that the compiler generates is actually quite
short! E.g. a single call instruction if &foo and $bar are already in
VM registers. Only the outcome is uncertain ;)



foo [EMAIL PROTECTED];  # always positionally


This makes perfect sense to me if you mean that the positionals
that foo requests are satisfied in the order provided by @array
without exceptions for pairs, not to mention subtypes of pairs
or things that do the Pair role etc.



foo *%hash;   # always named (hash keys taken as parameter names)


So that shall fail at compile time if foo has *anonymous* positionals?
E.g. a sig ($,$,$) or would there be a desparate attempt to call it as

  foo %hash<0>, %hash<1>, %hash<2>;

or aiming at whatever .[Int] means on a hash:

  foo %hash[0], %hash[1], %hash[2];

BTW, I would write a keyed sig as &foo:(:x,:y,:z).



Previously, you wasn't able to know whether you passed something
positionally or by name:

sub bar ($x) { grtz $x }
bar 42;   # 42 passed to &grtz positionally
bar a => 42;  # either the pair (a => 42) passed to &grtz
  # positionally or the number 42 passed by name

Under the new proposal, "grtz $x" always passes $x positionally. You
don't need &grtz's signature, nor do you need to know $x's type (is $x
a Pair?).


Yep. But you could attempt to dispatch .key on $x in grtz:

   sub grtz ($item)
   {
  say $x.key;
   }

and get a printout of 'Undef of Key' or so and 'a' respectively.
HiHi, or a 'method not understood' exception if .key is not applicable
to 42 ;)



Compare this with the old semantics:

  grtz $x;
  # $x is not a Pair? ==> $x passed positionally
  # else ==>
  #   &grtz expects a Pair as its first positional parameter?
  # ==> $x passed positionally
  #   else ==>
  # &grtz's signature lists a parameter named $x.key?
  #==> $x.value passed by name
  # else
  #   ==> $x passed positionally



Stuart Cook wrote:

And look, if you really wanted to, you could define your own
splat-style operator that works exactly as you describe.  But I don't
think it shoul

Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 12, 2005, at 11:04 AM, Gordon Henriksen wrote:

On Oct 12, 2005, at 09:41, Stevan Little wrote:

If you use the BUILD submethod, then you never need to worry about  
a that, everything is initialized for you by BUILDALL. Now, if you  
want to have a constructor which accepts positional arguments  
rather than named pairs (as the default does), then you have a  
valid need to override &new. Whether you should force this upon  
all your subclasses is a matter of opinion I think.


For varying definitions of initialized. I never much cared for the  
bare "poke stuff straight into my instance variables" constructor  
along the lines of:


sub new {
my($class, %ARGS);
return bless \%ARGS, $class;
}


Yes, that is a horrible idiom which I hope will die in Perl 6.

That more or less robs the constructor of the "behavior" part of  
"class = state + behavior." I need an opportunity to establish my  
invariants.


Well that is where BUILD comes in, you can do all sorts of mangling  
of parameters in BUILD so that it does what you want it to, there is  
no real need to put this behavior into &new.


Of course, when there is no such behavior, it saves a lot of  
repetitive typing in the class. C# 3 is finally growing a syntax  
that resolves this by having the language do the repetitive typing  
at the call site...


X x = new X{ Y = 1, Z = 2 };

means

X x = new X();
x.Y = 1;
x.Z = 2;

And X doesn't need anything but the default constructor.


Yes, this is exactly what the &new -> CREATE -> BUILDALL -> BUILD  
chain is doing too.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of "class  
methods" very easily.


  Class
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

Now, method dispatch for Bar will go first to it's class (eBar),  
then to any superclasses (eFoo), and any of their superclasses  
(Class), and so on, and so forth. A better diagram of this can be  
found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ 
docs/Method_Dispatch_w_EigenClasses.jpg).


This is more or less how class methods have to work. I would go a  
bit further, though. Too implement this:


Foo : Object
Foo : Bar

The runtime should use an inheritance tree as such:

Object
Class : Object
Foo : Object
Bar : Foo

_Object : Class
_Class : _Object
_Foo : _Class
_Bar : _Foo

Note that every declared class, including Object and Class  
themselves, have an anonymous Class subclass that precisely  
parallels the declared inheritance chain. (Chicken and egg problem?  
Probably. Object and Class are Special.)


This is pretty much the same thing that I am describing, except that  
I don't think that Class needs an anon-class/eigenclass. All object  
models need a cycle at the top, this keeps the "turtles-all-the-way- 
down" problem away. The usual place is to put the cycle in Class  
(Class is an instance of Class). If you add that anon-class, you  
break the cycle.


With this implementation, there are three places to put state: In  
MyObject (instance variable), in _MyObject (class instance  
variable), or outside of any instance (class variable). The class  
instance variable is the least useful of the three.


Well, I would argue that class instance variables are very useful,  
since that is where methods and attribute meta-objects are stored.  
But I think users should not have direct access to class instance  
variables. But yes, other than that you are correct.


Note: I don't see much value in invoking class methods through  
instances, since a Foo IS_NOT_A Class. If one wants to save the  
user typing ".class" when invoking class methods through an instance,


Yes, that is bad, another nasty p5 idiom I hope will go away.


I would tend toward resolving it as such:

class Foo {
class_method int Bar(int i) { return i * i; }
}

-- BECOMES --

# Common interface for Foo's class methods.
interface _IFoo {
method int Bar(int i);
}

# The anonymous Class.
class _Foo extends Class implements _IFoo {
int Bar(int i) { return i * i; }
}

# The visible class.
class Foo implements _IFoo {
# Forwards the call to the Class.
void Bar(...) { return this.Class.Bar(...); }
}


I think we can leave the interface part out, but yes, this is  
basically how the eigenclasses work :)


I'll leave the probably obvious role-based interpretation of this  
to those versed in such. :)


s/interface/role/ and you have the role based version ;)

Stevan






Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 12, 2005, at 10:48 AM, Gordon Henriksen wrote:
Actually, I wondered why you didn't suggest this earlier. :) I  
figured you were a step ahead of me: What if I want more than a  
boolean out of my class method?


Then you put the class methods back in :)

But then your Objective-C interface would need to change too.  
Although, the more complexity you introduce, the closer you get to  
the point when a Factory pattern is just as viable an approach as  
class methods.


Stevan


On Oct 12, 2005, at 10:27, Stevan Little wrote:

Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it  
"supportsFeatureB", you can just see if it does the "FeatureB"  
role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being  
treated as a role, ABC will actually consume all it's subroles,  
which means that ABC will DWIM too. In fact, we get even more from  
this system since we can check if one plug-in is capable of  
"doing" another, because this "just works"


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working  
code, I coded this up using the current meta-model prototype. You  
can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- 
MetaModel/t/38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:



class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a "class method" in it, which
# the consuming class will get as a "class method"
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}










—

Gordon Henriksen
[EMAIL PROTECTED]








Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Larry,

On Oct 11, 2005, at 8:47 PM, Larry Wall wrote:

On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:
: Hello all.
:
: I would like to propose that class methods do not get inherited  
along

: normal class lines.

I think most class methods should be written as submethods instead.


In which case they would not be inherited then. I (obviously) agree  
with you on that :)



You seem to be arguing that a class has no state, but my view is that,
in the abstract, a class encompasses the state of *all* its objects.
It just hasn't picked one particular object to be at the moment.


No, not that class has no state, but that with the currently specced  
classes we have inherited behaviors (class methods) but they do not  
inherit the accompanying state (class attributes) as well. I see this  
as potentially very problematic.



: == Instance Counting Class
:
: The most common example given for class methods is an "instance
: counter". Here is how one might (naively) look in Perl 6:
:
: class A {
: our $.count;
: method count (Class $c:) { $.count; }
: submethod BUILD {
: $.count++;
: }
: }

That's obviously broken--the count accessor should be a submethod  
to be

consistent, unless the explicit intent is that any subclass of A
return the count of A's.  Which, not surprisingly, is exactly what
you get below.  It should probably have been declared:

our $.A_count;

in that case.  And in which case you don't need the explicit accessor,
since one would have been provided because of the dot.  If you don't
want the autoaccessor, don't use the dot.


Yes, this example was purposefully broken, but also copied from  
several tutorial on "how to use class methods".




I suppose an argument could be made that autoaccessors for class vars
should be submethods by default.  Or maybe "my $.count" makes a  
submethod,

while "our $.A_count" makes a method.


I think that is probably not a bad idea. If we not going to inherit  
the class state, then we should not inherit the class method either.



: Clearly, we only have one instance of A, and one instance of B, so
: those numbers are wrong. It could be argued that since B is a  
subtype
: of A, we do have two A's, but the argument does not work in  
reverse.


Sure it does.  It doesn't matter whether B is a subtype of A or not,
you've given it an interface to code that counts A's.


True, that was probably a bad example (culled from other bad examples).


: But either way, I would argue that the results shown above are
: misleading, and probably not what the programmer intended.

That's certainly possible, but it wouldn't be the first time people
have been surprised that the computer did exactly what they asked it
to...  :-)


Also very true.


: Sure, you could do that, however, it complicates the meta-model
: unnecessarily. It is much easier to accomplish this using a  
subclass

: of Class.
:
: class CountingClass is Class {
: has $.counter;
: method count (CountingClass $c:) { $.counter; }
: method new (CountingClass $c: %params) {
: $.counter++;
: next;
: }
: }
:
: class A meta CountingClass {}
: class B meta CountingClass {}
:
: Now A and B both have their own counters neither of which interfere
: with one another.

Only by forcing people to repeat themselves as a matter of policy.
And policy could just as easily have added "our $.count" to B.  The
real trick would be to set up A such that you don't have to do  
anything

special in B.  I suppose we could say that, by default, if A isa B,
then A gets also gets whatever metaclass B has, not the standard
metaclass supplied by "class".


I considered this as well, it seems to make some sense that the  
metaclass of A is also the metaclass of B if A isa B. This would  
actually simplify a particular edge case with the eigenclasses that  
was problematic.


This diagram assumes we have inheritable class methods, and they are  
implemented using the eigenclasses.


  Class
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

The method dispatch for Bar will go first to it's class (eBar), then  
to any superclasses (eFoo), and any of their superclasses (Class),  
and so on, and so forth. When you introduce a custom metaclass like so:



  Class
^
:
CustomMeta
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

A "problem" occurs with method dispatch for Bar. First it will go to  
eBar, then to eFoo, then to CustomMeta, then to Class, etc, etc.  
Since Bar was not explicitly created with CustomMeta, this is not  
correct.


However, if the metaclasses act as you describe, this is then does  
exactly what it is supposed to. I think it is a sane approach  
personally.



But these are metaclasses, not classes.  You keep writing the type of
the invocant of class methods as Class, but I don't believe that  
anymore.


Sorry, just following the A12 examples :)


The type of the invocan

Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

It just occurred to me that the system shown below could be re- 
written to do away with class methods entirely.


class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role FeatureA {}
role FeatureB {}
role FeatureC {}

class AB {
does PlugIn;
does FeatureA;
does FeatureB;
}

class ABC {
does AB;
does FeatureC;
}

Now later on, instead of asking the PlugIn if it "supportsFeatureB",  
you can just see if it does the "FeatureB" role, like this:


if ($host.plugInClass.does('FeatureB')) {
# ... do something with FeatureB
}

This will work with the ABC plugin as well since AB is being treated  
as a role, ABC will actually consume all it's subroles, which means  
that ABC will DWIM too. In fact, we get even more from this system  
since we can check if one plug-in is capable of "doing" another,  
because this "just works"


if ($host.plugInClass.does('AB')) {
# ...
}

And since an example is better when it is backed up by working code,  
I coded this up using the current meta-model prototype. You can see  
it here: http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 
38_PlugIn_example.t


Stevan




On Oct 12, 2005, at 9:41 AM, Stevan Little wrote:

class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a "class method" in it, which
# the consuming class will get as a "class method"
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

role SupportsFeatureC {
method supportsFeatureC (Class $c:) { bool::true }
}

class ABC {
does AB;
does SupportsFeatureC;
}





Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Piers,

On Oct 12, 2005, at 5:22 AM, Piers Cawley wrote:

We definitely have two instances of A since, B.isa(::A). We also have
a fragile implementation of count.


:)

Sorry, I purposefully made it a kludge as that is usually the way the  
example is shown in most tutorials about class methods.




  class A {
our %.count_of

method count (Class $c:) { %.count_of{$c} }

method BUILD {
  $class = ($?SELF.class)

  @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)}


You can use the MRO here, which is an already linearized list of the  
inheritance tree (in C3 order) with all duplicates removed.




  for $class, [EMAIL PROTECTED] -> $c { %.count_of{$c}++ }
}

Where we're assuming I've got the syntax of 'for' right, and that
'ancestors' is a class method that returns all of a class's
ancestors. This might not work too well in the face of a dynamic
inheritance tree, but it should be possible to work around. Something
like this might work:

   Class A {
 our %.instance_count_of

 method count (Class $c: ?$with_descendents = undef) {
   my @interesting_classes = $c;
   if $with_descendents {
 push @interesting_classes, *($c.all_subclasses);
   }
   [+] %.instance_count_of(@interesting_classes)
 }

 method BUILD {
   %.instance_count_of($?SELF.class)
 }
   }

Where we're assuming that a class can find all its subclasses

--
Piers Cawley <[EMAIL PROTECTED]>
http://www.bofh.org.uk/






Re: Proposal to make class method non-inheritable

2005-10-12 Thread Stevan Little

Gordon,

On Oct 11, 2005, at 9:10 PM, Gordon Henriksen wrote:

On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:

I would like to propose that class methods do not get inherited along
normal class lines.


You mean, make them *not methods?* Because it's not a method unless it
has an invocant, as far as I'm concerned. (Method implies  
polymorphism.)


No, they would still have an invocant. That invocant would be an anon- 
class which itself is an instance of Class. It works like so:


(First, lets make a legend)

  --> is instance of
  ..> is subclass of

NOTE: Class means the class named "Class", this distinction is  
important.


When you create the class Foo, this is what you have:

  Class
^
|
   Foo

Foo is an instance of class Class (Class itself is an instance of  
class Class too, but thats only slightly relevant here).


When you add a class method (one which cannot be inherited), it is  
done with an eigenclass. This changes the above structure into this:


  Class
^
:
  eFoo
^
|
   Foo

Now, we have created an anon-class (or eigenclass), whose entire  
purpose is to hold the class methods of Foo. Since the eigenclass is  
a subclass of Class, then all of Class's methods are inherited. This  
means that our method dispatcher does not need to know about class  
methods as a special case, as far as it is concerned, they are just  
normal instance methods on Foo (which itself is an instance of eFoo,  
which is then a subclass of Class).


Now, why are they not inherited. Lets expand this diagram a little more:

Class
  ^
+-|+
|  |
   Foo<...Bar

So Foo and Bar are both instances of Class, and Bar is a subclass of  
Foo. It is fairly straightforward, but now lets introduce the  
eigenclasses to hold class methods.


Class
  ^
..:.
:  :
  eFooeBar
^  ^
|  |
   Foo<...Bar

Now, method dispatch for Foo will go to eFoo (since Foo is an  
instance of eFoo, and method dispatch always starts at the class-of  
the instance), and it will continue up to Class (since Class is the  
superclass of eFoo). The same goes for Bar, first to eBar, then to  
Class. Since eFoo and eBar are not connected, then normal method  
dispatching does not go along those lines.


Now, this is not to say that it cannot be made to do so. A slight  
change to the above diagram allows for inheritence of "class methods"  
very easily.


  Class
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

Now, method dispatch for Bar will go first to it's class (eBar), then  
to any superclasses (eFoo), and any of their superclasses (Class),  
and so on, and so forth. A better diagram of this can be found here  
(http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ 
Method_Dispatch_w_EigenClasses.jpg).




: Let's start by making a very basic definition of an *object*,
: ignoring any implementation details or specifics.
:
:   object == state + behavior

I don't see how this is a bad thing. Classes don't have state. That's
their lot in life. Que sera! Inheritance of behavior alone is useful.


Classes do have state though. They have class attributes:

class Foo {
our $.bar;
my $.baz;
}

that state is just not inherited.

I am not actually arguing that inheritance of just behavior is not  
useful, more that inheritance of behavior *without the accompanying  
state* is not useful, and in many cases wrong.




My primary want for class methods, as a whole, is to provide this sort
of interface in Objective-C:

@interface Host : NSObject {
- (Class)plugInClass;
- (void)setPlugInClass:(Class) plugInClass;
}

@interface PlugIn : NSObject {
- (BOOL)initWithHost:(Host *)host;
+ (BOOL)supportsFeatureA;
+ (BOOL)supportsFeatureB;
}

... later ...
if ([[host plugInClass] supportsFeatureA]) {
... expose UI element ...
}


My Objective-C is very rusty, but let met see if I understand what  
you are doing.


Host has-a Class object, which it uses as a plugInClass. Your PlugIn  
then has class methods (supportsFeatureA, supportsFeatureB) which can  
be used by the Host to query the capabilities of its plugInClass.


This type of thing could be accomplished with Roles.

class Host {
my $.plugInClass;
}

role PlugIn {
method initWithHost (Host $h:) { ... }
}

role SupportsFeatureA {
# yes, this Role has a "class method" in it, which
# the consuming class will get as a "class method"
method supportsFeatureA (Class $c:) { bool::true }
}

role SupportsFeatureB {
method supportsFeatureB (Class $c:) { bool::true }
}

class AB {
does PlugIn;
does SupportsFeatureA;
does SupportsFeatureB;
}

One could argue that it is more typing, however, I think that in the  
long run, it will be less typing since you never need to repeat the  
supportsFeatureA or supportsFeatureB method, just con

Re: multiline comments

2005-10-12 Thread Juerd
Alfie John skribis 2005-10-12 15:28 (+1000):
> Does Perl6 support multiline comments?

All incarnations of Perl have allowed us to begin multiple subsequent
lines with the comment glyph '#'. I am sure Perl 6 will not break this
tradition.


Juerd
-- 
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html 
http://convolution.nl/gajigu_juerd_n.html


Re: Proposal to make class method non-inheritable

2005-10-12 Thread Piers Cawley
Stevan Little <[EMAIL PROTECTED]> writes:

> Hello all.
>
> I would like to propose that class methods do not get inherited along
> normal class lines.
>
> I think that inheriting class methods will, in many cases, not DWIM.
> This is largely because your are inheriting behavior, and not state
> (since class attributes are not inheritable). Let me explain in more
> detail.
>
> Let's start by making a very basic definition of an *object*,
> ignoring any implementation details or specifics.
>
>object == state + behavior
>
> This statement assumes that *objects* at their core are a unique
> state coupled with a collection of behaviors to act upon that
> particular state. Of course we are ignoring all the other class/meta/
> inheritence junk for now.
>
> To take away the behavior, and only be left with state would degrade
> our object to the level of C struct or Pascal-style record-type. To
> take away the state, and only be left with behavior, would basically
> leave a module/package or some pseudo-random collection of functions.
>
> So at this point, I think it is safe to say that an *object* should
> have both state and behavior.
>
> Now, back down from the theoretical cloud to reality. I would like to
> show some canonical class-method examples (and in some cases, show
> how they are broken), then show how they might be better accomplished
> in Perl 6 without the need for class methods to be inherited.
>
> == Instance Counting Class
>
> The most common example given for class methods is an "instance
> counter". Here is how one might (naively) look in Perl 6:
>
> class A {
>  our $.count;
>  method count (Class $c:) { $.count; }
>  submethod BUILD {
>  $.count++;
>  }
> }
>
> Each time an instance of A is created the counter is incremented. So
> that ...
>
> A.count; # 0
> A.new;
> A.count; # 1
>
> Now this makes sense, until we subclass A.
>
> class B is A {}
>
> A.count; # still 1
> B.new; # calls A::BUILD
>
> A.count; # 2
> B.count; # 2
>
> Clearly, we only have one instance of A, and one instance of B, so
> those numbers are wrong. It could be argued that since B is a subtype
> of A, we do have two A's, but the argument does not work in reverse.
> But either way, I would argue that the results shown above are
> misleading, and probably not what the programmer intended.

We definitely have two instances of A since, B.isa(::A). We also have
a fragile implementation of count.

  class A {
our %.count_of

method count (Class $c:) { %.count_of{$c} }

method BUILD {
  $class = ($?SELF.class)

  @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)}

  for $class, [EMAIL PROTECTED] -> $c { %.count_of{$c}++ }
}

Where we're assuming I've got the syntax of 'for' right, and that
'ancestors' is a class method that returns all of a class's
ancestors. This might not work too well in the face of a dynamic
inheritance tree, but it should be possible to work around. Something
like this might work:

   Class A {
 our %.instance_count_of

 method count (Class $c: ?$with_descendents = undef) {
   my @interesting_classes = $c;
   if $with_descendents {
 push @interesting_classes, *($c.all_subclasses);
   }
   [+] %.instance_count_of(@interesting_classes)
 }

 method BUILD {
   %.instance_count_of($?SELF.class)
 }
   }

Where we're assuming that a class can find all its subclasses 

-- 
Piers Cawley <[EMAIL PROTECTED]>
http://www.bofh.org.uk/


RE: Proposal to make class method non-inheritable

2005-10-12 Thread Gordon Henriksen
On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote:

> I would like to propose that class methods do not get inherited along  
> normal class lines.

You mean, make them *not methods?* Because it's not a method unless it
has an invocant, as far as I'm concerned. (Method implies polymorphism.)


: Let's start by making a very basic definition of an *object*,  
: ignoring any implementation details or specifics.
: 
:   object == state + behavior

I don't see how this is a bad thing. Classes don't have state. That's
their lot in life. Que sera! Inheritance of behavior alone is useful.

My primary want for class methods, as a whole, is to provide this sort
of interface in Objective-C:

@interface Host : NSObject {
- (Class)plugInClass;
- (void)setPlugInClass:(Class) plugInClass;
}

@interface PlugIn : NSObject {
- (BOOL)initWithHost:(Host *)host;
+ (BOOL)supportsFeatureA;
+ (BOOL)supportsFeatureB;
}

... later ...
if ([[host plugInClass] supportsFeatureA]) {
... expose UI element ...
}

Rather than having to make plugin creation cheap so that I can do this:

class Host {
public Type PlugInClass {
get { ... }
set { ... }
}
}

class PlugIn {
public bool Host { get; }
public abstract bool SupportsFeatureB { get; }
public abstract bool SupportsFeatureA { get; }
}

... later ...
PlugIn plugIn = (PlugIn) Activator.CreateInstance(host.PlugInClass);
if (plugIn.SupportsFeatureA) {
... expose UI element ...
}

Another alternative is to introduce a PlugInFactory. Which might be
better in complex scenarios. But it's often overkill. And it's certainly
more typing.

In C#, I might also use attributes to decorate the plugin Type. But
those, too, are more typing than class methods (and also weakly typed).

Also, of course, inheriting constructors is nice. Of course, it opens up
the whole "designated constructor" can of worms. But that's okay; if
you're subclassing, it's your responsibility to make it work

-- 
 
Gordon Henriksen
[EMAIL PROTECTED]