Re: Conceptual questions about Objects

2008-04-05 Thread chromatic
On Saturday 05 April 2008 17:10:57 Larry Wall wrote:

> On Fri, Apr 04, 2008 at 09:41:26PM -0500, John M. Dlugosz wrote:

> > I suppose any object would do, it doesn't have to be "but undefined", or
> > created using that Class{hash} syntax?
>
> Possibly.  Haven't really thought through the ramifications, and it
> feels a bit like the problem of confusing clone with new.  It would
> be pretty easy for idioms to arise that create a lot of useless
> temporary objects.  You can only sweep so much under the carpet of
> "the optimizer could fix it"...
>
> In any case, the programmer really needs to keep straight when
> an object is being used for its value vs when it's being used
> for its type.  Maybe that's not an issue here.

Parrot-wise, right now that's somewhat more expensive than it should be.  The 
carpet's not as large as I wish it were.  (However it's possible not to 
require instantiating a new object or class for type checks, let's do that!)

> We have another possible level of granularity there too, insofar as we
> could trust a single multi or a proto that represents all multis in
> its scope.  Maybe a proto exported from within a class automatically
> conveys trust to all normal multis (of the same name) declared the
> import scope.

Something about that I like.

> > Also, since classes can be re-opened, anyone can grab trust from any
> > class anyway, just by declaring a new method inside that class.
> Well, sure.  But whenever the programmer does that, the Perl 6 compiler
> will automatically send email to the programmer's supervisor.  :)

If you mean "The World's Most Maintainable Programming Language", that was an 
April Fool's joke.

-- c


Re: Conceptual questions about Objects

2008-04-05 Thread Larry Wall
On Fri, Apr 04, 2008 at 09:41:26PM -0500, John M. Dlugosz wrote:
> But see my q's to Audrey.  Why does it need the qualified name if the same 
> class as $obj's declared type,

We could conceivably relax that if $obj has a declared type.  But on
the other hand requiring the class name is pretty good documentation
for what could be viewed as a violation of propriety, even if the
other class has trusted us.  It feels right to me from a huffman
coding point of view, anyway.  I'm not opposed to making the user
jump through a few extra hoops for easily misunderstood constructs.
But maybe you can argue me out of it.  :)

> and just how is that being parsed and/or implemented?

expect_term -> post -> dotty: methodop -> name

So it would be implemented as a semantic constraint in any case, not
a syntactic one.

>> See S12:680 and following for how to pass protoobjects representing
>> partial construction without having to actually create intermediate
>> objects.
>>
>>   
> OK, I didn't understand what that was about when I read it.  Now I see it 
> as analogous to the base/member syntax in C++.
>
> I suppose any object would do, it doesn't have to be "but undefined", or 
> created using that Class{hash} syntax?

Possibly.  Haven't really thought through the ramifications, and it
feels a bit like the problem of confusing clone with new.  It would
be pretty easy for idioms to arise that create a lot of useless
temporary objects.  You can only sweep so much under the carpet of
"the optimizer could fix it"...

In any case, the programmer really needs to keep straight when
an object is being used for its value vs when it's being used
for its type.  Maybe that's not an issue here.

>> Every class maintains its own concrete, which is of no business to
>> anyone else, including derived classes.  There is nothing like
>> protected in Perl 6.  The closest you can get to it is "trusts",
>> and that's independent of class hierarchy.
>>   It is my understanding that even Bjarne thinks "protected" is a bad idea
>> these days...
>>   
>
> OK, so what is the more general mechanism of providing different interfaces 
> to different sets of trusted consumers?  There is the "protected interface" 
> that I document to explain how a derived class is to extend the 
> functionality, and it has access to things the caller doesn't, besides just 
> being able to override functions.  If there is no special mechanism just 
> for derived classes, I suppose you must have something better in mind.
>
> For example, sometimes a particular module (namespace, whatever) might need 
> a special insider interface, because they work together.  But not total 
> trust like its own implementation!  Another contract, distinct from the 
> public interface contract.  That's a good name for it: multiple contracts.  
> "trusted" hands out access to all private instance data, which is a special 
> case.

Feels like it wants some form of delegation to me.  On the other
hand, contracts are generally expressed with roles in Perl 6, so
maybe there could be some way of limiting trust to the granularity
of a particular role's interface.

> Oh, and in C++, friendship can be granted to a function as well as to a 
> class.  I suppose there is less need in Perl 6 since a global function can 
> be written as a method and exported.  But consider a function that operates 
> on two different objects; it can only be the method of one.  I don't need 
> to make the whole other class trusted, just this one function.

We have another possible level of granularity there too, insofar as we
could trust a single multi or a proto that represents all multis in
its scope.  Maybe a proto exported from within a class automatically
conveys trust to all normal multis (of the same name) declared the
import scope.

> Also, since classes can be re-opened, anyone can grab trust from any class 
> anyway, just by declaring a new method inside that class.

Well, sure.  But whenever the programmer does that, the Perl 6 compiler
will automatically send email to the programmer's supervisor.  :)

Larry


Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

Many thanks.

Larry Wall larry-at-wall.org |Perl 6| wrote:

self!BaseName::attr should work, assuming BaseName trusts us.

  
Because it is an accessor function, not a syntax to reference a variable 
in another scope.  Got it.


But see my q's to Audrey.  Why does it need the qualified name if the 
same class as $obj's declared type, and just how is that being parsed 
and/or implemented?



See S12:680 and following for how to pass protoobjects representing
partial construction without having to actually create intermediate
objects.

  
OK, I didn't understand what that was about when I read it.  Now I see 
it as analogous to the base/member syntax in C++.


I suppose any object would do, it doesn't have to be "but undefined", or 
created using that Class{hash} syntax?

Every class maintains its own concrete, which is of no business to
anyone else, including derived classes.  There is nothing like
protected in Perl 6.  The closest you can get to it is "trusts",
and that's independent of class hierarchy.
  
It is my understanding that even Bjarne thinks "protected" is a bad idea

these days...
  


OK, so what is the more general mechanism of providing different 
interfaces to different sets of trusted consumers?  There is the 
"protected interface" that I document to explain how a derived class is 
to extend the functionality, and it has access to things the caller 
doesn't, besides just being able to override functions.  If there is no 
special mechanism just for derived classes, I suppose you must have 
something better in mind.


For example, sometimes a particular module (namespace, whatever) might 
need a special insider interface, because they work together.  But not 
total trust like its own implementation!  Another contract, distinct 
from the public interface contract.  That's a good name for it: multiple 
contracts.  "trusted" hands out access to all private instance data, 
which is a special case.


Oh, and in C++, friendship can be granted to a function as well as to a 
class.  I suppose there is less need in Perl 6 since a global function 
can be written as a method and exported.  But consider a function that 
operates on two different objects; it can only be the method of one.  I 
don't need to make the whole other class trusted, just this one function.


Also, since classes can be re-opened, anyone can grab trust from any 
class anyway, just by declaring a new method inside that class.


--John



Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

Ryan Richter ryan-at-tau.solarneutrino.net |Perl 6| wrote:

You've declared method a twice here. 


According to S12, "You may write your own accessors to override any or all of the 
autogenerated ones."



has $!a;
method a { $!a }

The variable is always really the $! form.

  



I'm catching on.


Re: Conceptual questions about Objects

2008-04-04 Thread Larry Wall
On Fri, Apr 04, 2008 at 07:01:32PM -0500, John M. Dlugosz wrote:
> That is, a derived class, assuming it was trusted, could use 
> $self!BaseName::attr to prevent confusion with something named self!attr 
> that ordinarily hides it.

Which is never a problem anyway, since private attributes are never,
ever inherited, and are even off in their own namespace so they're
completely invisible to a derived class.  Suppose you derive:

A -> B -> C

Suppose B defines $!foo as a private attribute.  This is invisible to
C, to the extent that if A defines a public $.foo, it is visible in C.
Private names are never allowed to clobber public names.

> And a syntax question for you:  Above, I just assumed $self is the 
> explicitly-named invocant.  How do you access the attribute if using the 
> self keyword, which does not have a sigil?  If it has $!attr and has 
> @!attr, that is important.  I realize this is not an issue when using 
> method calls (including accessor functions) on self.

self!BaseName::attr should work, assuming BaseName trusts us.

>>> Does the variable used as the invocant, or return value if it is an 
>>> expression,
>> > have to be statically typed as being of the identical class?
>>
>> The $obj above must be evaluated to an object of class MyClass.
>>
>> AFAICS, the spec doesn't really say if a derived class needs to explicitly 
>> trust YourClass for it to be used this way:
>>
>> class MyDerivedClass is MyClass {};
>> YourClass.foo(MyDerivedClass.new(attr => 1)); # Not sure if this works.
> "the spec doesn't say"  hence my confusion.  So will Larry rule on that, or 
> should we discuss it in detail, or should I just make up something in my 
> proposed doc edit?

As pointed out elsewhere, the spec does say, if you shake it hard
enough. :)

> If your example does work, it means that in general the BUILD can comb 
> arguments out for each class in the hierarchy, rather than only being 
> allowed to specify arguments to defined constructors for the base classes, 
> as in C++.  Is that good or bad?  Just how would you say the latter, 
> anyway?

See S12:680 and following for how to pass protoobjects representing
partial construction without having to actually create intermediate
objects.

>>> If class C { has $.a; ... }, then I understand that members may refer to
>>> $.a directly but outside of the scope of members defined in the class
>>> they can only be reached by accessors, a() as a method call.
>>
>> Well, $.a is exactly the same as $(self.a) -- see S12/"are just shorthands 
>> of C" for the definition.
>>
>> Methods in class C may call $!a, which is the private accessor method.
>> Outside the scope, private methods of class C are invisible.
>>
> OK, I think I'm beginning to see. $.x is not "variable-like", but a 
> shortcut for $(self.x()), and always is.  You don't name an object with 
> this form, ever, as it only works on self. 
> That is why the ! forms don't have a "unary form".  It could certainly be 
> explained better in the document.  Your retelling is already helpful.

Well, the main reason there is no unary ! form is actually that
prefix: already means something else in C-derived languages.  :)

>>> But, it is also stated that in derived and trusted classes, and even in
>>> the class itself, $.a is an accessor call?
>>
>> Well, $.a is merely shorthand for $(self.a) so derived classes can call it 
>> just fine.  However in trusted classes, $.a wouldn't make much sense,
>> as you need to use either $obj.a or $obj!YourClass::a there.
>>
>>> Is this accessor different from the
>>> function form used outside the class? Why keep the variable syntax?
>>
>> Because it's jolly convenient, especially in interpolated strings, I 
>> suppose:
>>
>> say "My position is $.x - $.y - $.z";
>>
>>> I'm getting a picture of 3 forms of access: Really direct, direct but
>>> asking the class to access it rather than knowing how storage works, and
>>> indirect that may involve your own code to do other things besides just
>>> get/set the attribute. But I think the middle one can be handled
>>> invisibly by the compiler -- it's no different from a tied hash.
>>
>> The middle one is not that different from the first one, because from an 
>> implementation viewpoint, once YourClass trusts MyClass, then code in 
>> MyClass might as well have knowledge about how the storage works.
> But it looks like there is no middle one.

Yes, there is no middle, by design.  It's either concrete storage,
hence non-virtual, or it's abstract and hence virtual.  And even the
class itself is encouraged to distinguish those usages, so it should
use $!foo when it means the storage, and it should use $.foo when it
means the concept, so that a derived class can override it.

> Besides "how the storage works", I'm thinking of the multiple-base 
> composition issues.  The attribute may be stored in different places 
> depending on the concrete type, and the method is called on a type derived 
> from the one it is written in.

Eve

Re: Conceptual questions about Objects

2008-04-04 Thread Mark J. Reed
You have completely lost me, John.  What the heck are you asking?

$obj.foo: calls public method "foo" on the object referenced by $obj.

$.foo  shorthand for calling "foo" on self (in scalar context).

As I understand it, although I could be confused, these have
absolutely nothing to do with whether or not there's a private "foo"
attr, other than the convenience of being able to declare that the
public "foo" method is actually an accessor for a private "foo" attr
via the "has" syntax.


Re: Conceptual questions about Objects

2008-04-04 Thread chromatic
On Friday 04 April 2008 16:56:44 Audrey Tang wrote:

> In other words, there needs to be no real hard attribute "bar", no
> matter if you call the "bar" method as self.bar(), $.bar(), or simply
> $.bar.

That's what I was trying to say with "uniform access principle", except that 
Audrey's version is much clearer.

-- c


Re: Conceptual questions about Objects

2008-04-04 Thread Audrey Tang

John M. Dlugosz wrote:

Seriously,
Does this mean that the access of private attributes from trusted
classes is a "different form"? And that's why you need the qualified
syntax when I think it should not be necessary in all cases? Or should
that passage really say "not in non-trusted classes, including derived
classes"?


It's a different form.  Line 1207:

(Private accessors are never virtual, and must be package qualified
if called from a trusted scope other than our own.  That is, it's
either C or C<$obj!TrustsMe::attr().>)

The reason is, I suspect, that what "trusts" does is putting a 
!TrustsMe::attr() into the trustee's scope, instead of somehow shadowing 
its own !attr() symbol.


Cheers,
Audrey


Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote:

"Every Idiot declaration... "
Sorry, must be a font problem

Seriously,
Does this mean that the access of private attributes from trusted 
classes is a "different form"?  And that's why you need the qualified 
syntax when I think it should not be necessary in all cases?  Or should 
that passage really say "not in non-trusted classes, including derived 
classes"?


--John


John M. Dlugosz wrote:


OK, trust is not implicit on derived classes. Is that because there is
no rule that says it is, or is there a mention of that somewhere in the
official docs?


There is.  S12 Line 561:

Every I declaration also declares a corresponding private
I storage location, and the exclamation form may be used
only in the actual class, not in derived classes.

Cheers,
Audrey





Re: Conceptual questions about Objects

2008-04-04 Thread Darren Duncan

John M. Dlugosz wrote:

Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote:

John M. Dlugosz wrote:

A method can refer to private attributes etc. in other objects than
self. This is unlike Smalltalk and like C++. Which objects? Obviously,
those that _have_ them in the first place.


Correct, though those classes also has to trust the calling class:

class MyClass { has $!attr; trusts YourClass }
class YourClass {
method foo (MyClass $obj) {
$obj!MyClass::attr; # Access to $obj's private attr
}
}

So, do classes trust their derived classes by default?  Is trust itself 
inherited?


No, there is no implicit trust, even of subclasses.  For if that were the 
case, you would have a couple of problems at least:


1. A major advantage of having things private is that it lets subclasses 
not have to worry about implementation details of parent classes. 
Subclasses can declare their own private or public attributes or methods 
with the same names as private attributes or methods of their parents, and 
they won't conflict.  If the parent adds new privates later, it doesn't 
have to worry about conflict with any subclasses.  By contrast, typical 
(hash-based) Perl 5 classes have to deal with this problem all the time as 
all attributes and methods are actually public even if undocumented.


2. It would be very easy for anyone to defeat the security that the privacy 
is supposed to give, without the class being exposed having any say about it.


-- Darren Duncan


Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

I understand your example.  In fact, it further clarifies your earlier note.

But that's not what I meant.  I was thinking that access was through a 
variable, not understanding the real point of the syntax.


Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote:

John M. Dlugosz wrote:

That seems to be saying that using the method-call form is preferred, as
it abstracts whether it is a real hard attribute or not.


Er, it is not so.

The $.foo notation is good not only for calling accessors, but also as 
a way to specify context when calling oneself's methods.  Consider:


class Foo {
method bar ($x, $y) { ... }
method baz (
$.bar: 1, 2;
@.bar: 3, 4;
}
}

Here we are simply typing $.bar as a shorthand of $(self.bar), and 
@.bar as @(self.bar), as well as supplying them with arguments; they 
do not mandate that there exists a "bar" attribute for our class.


In other words, there needs to be no real hard attribute "bar", no 
matter if you call the "bar" method as self.bar(), $.bar(), or simply 
$.bar.


Cheers,
Audrey





Re: Conceptual questions about Objects

2008-04-04 Thread Audrey Tang

John M. Dlugosz wrote:


OK, trust is not implicit on derived classes. Is that because there is
no rule that says it is, or is there a mention of that somewhere in the
official docs?


There is.  S12 Line 561:

Every I declaration also declares a corresponding private
I storage location, and the exclamation form may be used
only in the actual class, not in derived classes.

Cheers,
Audrey


Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

Darren Duncan darren-at-darrenduncan.net |Perl 6| wrote:


A method is defined within a role or class, as is an attribute.  A 
private attribute can generally be referenced only by a method 
declared in the same role or class as said attribute.


I think that's not right.  A private attribute defined in a role becomes 
a private attribute of the composed class, so may be referred to from 
other roles or the main class definition.  In contrast, a "my" variable 
inside the role is private to that role's block.  Though it is put into 
the object's attribute list (the scope is per-instance), it has no name 
outside of the block.



A method can reference its own role's/class's private attributes for 
any objects of that role/class, regardless of whether said object is 
the current method call's invocant or not.

OK, taking "class" only, not "role".




If a role or class is composed into another class or is subclassed, the
(for example) subclass can not reference the private attributes of its 
parent class.


As an exception to the above, if a particular class says that it 
"trusts" a particular other class (using "trusts Otherclass;" as a 
trait), then the trusted class can also reference the privates of the 
first class.
OK, trust is not implicit on derived classes.  Is that because there is 
no rule that says it is, or is there a mention of that somewhere in the 
official docs?







Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

Audrey Tang audreyt-at-audreyt.org |Perl 6| wrote:

John M. Dlugosz wrote:

A method can refer to private attributes etc. in other objects than
self. This is unlike Smalltalk and like C++. Which objects? Obviously,
those that _have_ them in the first place.


Correct, though those classes also has to trust the calling class:

class MyClass { has $!attr; trusts YourClass }
class YourClass {
method foo (MyClass $obj) {
$obj!MyClass::attr; # Access to $obj's private attr
}
}

So, do classes trust their derived classes by default?  Is trust itself 
inherited?


In this example, as in S12, why do you have to specify the MyClass:: 
prefix?  I thought you would only need this to refer to a specific class 
in the ISA list and not necessarily the one defined in or visible in the 
declared class.


That is, a derived class, assuming it was trusted, could use 
$self!BaseName::attr to prevent confusion with something named self!attr 
that ordinarily hides it.


And a syntax question for you:  Above, I just assumed $self is the 
explicitly-named invocant.  How do you access the attribute if using the 
self keyword, which does not have a sigil?  If it has $!attr and has 
@!attr, that is important.  I realize this is not an issue when using 
method calls (including accessor functions) on self.



Does the variable used as the invocant, or return value if it is an 
expression,

> have to be statically typed as being of the identical class?

The $obj above must be evaluated to an object of class MyClass.

AFAICS, the spec doesn't really say if a derived class needs to 
explicitly trust YourClass for it to be used this way:


class MyDerivedClass is MyClass {};
YourClass.foo(MyDerivedClass.new(attr => 1)); # Not sure if this works.
"the spec doesn't say"  hence my confusion.  So will Larry rule on that, 
or should we discuss it in detail, or should I just make up something in 
my proposed doc edit?


If your example does work, it means that in general the BUILD can comb 
arguments out for each class in the hierarchy, rather than only being 
allowed to specify arguments to defined constructors for the base 
classes, as in C++.  Is that good or bad?  Just how would you say the 
latter, anyway?



If class C { has $.a; ... }, then I understand that members may refer to
$.a directly but outside of the scope of members defined in the class
they can only be reached by accessors, a() as a method call.


Well, $.a is exactly the same as $(self.a) -- see S12/"are just 
shorthands of C" for the definition.


Methods in class C may call $!a, which is the private accessor method.
Outside the scope, private methods of class C are invisible.

OK, I think I'm beginning to see. 
$.x is not "variable-like", but a shortcut for $(self.x()), and always 
is.  You don't name an object with this form, ever, as it only works on 
self. 

That is why the ! forms don't have a "unary form".  It could certainly 
be explained better in the document.  Your retelling is already helpful.





But, it is also stated that in derived and trusted classes, and even in
the class itself, $.a is an accessor call?


Well, $.a is merely shorthand for $(self.a) so derived classes can 
call it just fine.  However in trusted classes, $.a wouldn't make much 
sense,

as you need to use either $obj.a or $obj!YourClass::a there.


Is this accessor different from the
function form used outside the class? Why keep the variable syntax?


Because it's jolly convenient, especially in interpolated strings, I 
suppose:


say "My position is $.x - $.y - $.z";


I'm getting a picture of 3 forms of access: Really direct, direct but
asking the class to access it rather than knowing how storage works, and
indirect that may involve your own code to do other things besides just
get/set the attribute. But I think the middle one can be handled
invisibly by the compiler -- it's no different from a tied hash.


The middle one is not that different from the first one, because from 
an implementation viewpoint, once YourClass trusts MyClass, then code 
in MyClass might as well have knowledge about how the storage works.

But it looks like there is no middle one.

Besides "how the storage works", I'm thinking of the multiple-base 
composition issues.  The attribute may be stored in different places 
depending on the concrete type, and the method is called on a type 
derived from the one it is written in.





How private is private? I wonder if what you've called private things
are really more like "protected" in C++ (accessible by the derived
class) and that 'my' attributes are really private, as are submethods.
It's all confused. Who is allowed to access what?


No, private methods are not accessible from derived classes, unless 
the base class explicitly trusts them -- See L12/"the exclamation form 
may be used only in the actual class, not in derived classes".


Cheers,
Audrey






Re: Conceptual questions about Objects

2008-04-04 Thread Audrey Tang

John M. Dlugosz wrote:

That seems to be saying that using the method-call form is preferred, as
it abstracts whether it is a real hard attribute or not.


Er, it is not so.

The $.foo notation is good not only for calling accessors, but also as a 
way to specify context when calling oneself's methods.  Consider:


class Foo {
method bar ($x, $y) { ... }
method baz (
$.bar: 1, 2;
@.bar: 3, 4;
}
}

Here we are simply typing $.bar as a shorthand of $(self.bar), and @.bar 
as @(self.bar), as well as supplying them with arguments; they do not 
mandate that there exists a "bar" attribute for our class.


In other words, there needs to be no real hard attribute "bar", no 
matter if you call the "bar" method as self.bar(), $.bar(), or simply $.bar.


Cheers,
Audrey


Re: Conceptual questions about Objects

2008-04-04 Thread chromatic
On Friday 04 April 2008 16:31:56 John M. Dlugosz wrote:

> chromatic chromatic-at-wgz.org |Perl 6| wrote:

> > It shouldn't be.
> So you are saying that...

I was talking about syntax.

> In that case, why allow the variable-name form at all?

Because they're variables.  Sure, they're instance variables, but like hearsay 
and conjecture are *kinds* of evidence, instance variables are kinds of 
variables.  Sometimes it's nice to be able to assign to them, for example:

method in_place_attribute_assignment ($.a, $.b, $.c);

> >> Why keep the variable syntax?

> > Uniform access principle.  See also "Why Java programmers fetishize their
> > IDEs, reason #482: autogeneration of metric boat-loads of
> > accessors/mutators at just the click of a button."
>
> That seems to be saying that using the method-call form is preferred, as
> it abstracts whether it is a real hard attribute or not.  Since my
> question was why keep the variable-name form, I think we are not
> understanding each other.

Yeah, I think you're asking the question backwards.  Maybe you should ask 
instead "Why are there accessor methods for instance variables?  Why not 
support only direct instance variable access?"

> >> I'm getting a picture of 3 forms of access:  Really direct, direct but
> >> asking the class to access it rather than knowing how storage works, and
> >> indirect that may involve your own code to do other things besides just
> >> get/set the attribute.  But I think the middle one can be handled
> >> invisibly by the compiler -- it's no different from a tied hash.

> > That really depends on how much external syntax you want to change if you
> > change the internal representation of an object.  For me, that's
> > approximately none.

> I don't understand that sentence at all.  Again, "invisibly by the
> compiler" sounds like what you want.

I'm still talking about syntax; I don't care for lvalue methods that look more 
like methods, not variables.  Maybe that's a personal failing.

I also could be completely misunderstanding what you're asking.  I *am* 
supposed to be researching a J2EE/SOA article at the moment.

-- c


Re: Conceptual questions about Objects

2008-04-04 Thread Ryan Richter
On Fri, Apr 04, 2008 at 06:31:56PM -0500, John M. Dlugosz wrote:
> chromatic chromatic-at-wgz.org |Perl 6| wrote:
> >It shouldn't be.
> >  
> So you are saying that in the example of
> 
>class C {
>   has $.a;
>   method a ($self:)

You've declared method a twice here.  has $.a is equivalent to

has $!a;
method a { $!a }

The variable is always really the $! form.

-ryan


Re: Conceptual questions about Objects

2008-04-04 Thread John M. Dlugosz

chromatic chromatic-at-wgz.org |Perl 6| wrote:

It shouldn't be.
  

So you are saying that in the example of

   class C {
  has $.a;
  method a ($self:)
 {
 side_effect();
 return $self.a;
 }
  } # end C

   class D is C {
  method foo ($self:)
 {
 # ...
 $x = $self.a;
 # ...
 }
  } # end D

that the variable-notation access in foo will call the explicit accessor 
method C::a?  I suppose the use of $self.a in method a would be an 
infinite loop, and must be $self!a to work.


In that case, why allow the variable-name form at all? 

Why keep the variable syntax? 



Uniform access principle.  See also "Why Java programmers fetishize their 
IDEs, reason #482: autogeneration of metric boat-loads of accessors/mutators 
at just the click of a button."


  
That seems to be saying that using the method-call form is preferred, as 
it abstracts whether it is a real hard attribute or not.  Since my 
question was why keep the variable-name form, I think we are not 
understanding each other.




I'm getting a picture of 3 forms of access:  Really direct, direct but
asking the class to access it rather than knowing how storage works, and
indirect that may involve your own code to do other things besides just
get/set the attribute.  But I think the middle one can be handled
invisibly by the compiler -- it's no different from a tied hash.



That really depends on how much external syntax you want to change if you 
change the internal representation of an object.  For me, that's 
approximately none.
  
I don't understand that sentence at all.  Again, "invisibly by the 
compiler" sounds like what you want. 






Re: Conceptual questions about Objects

2008-04-04 Thread Darren Duncan

John M. Dlugosz wrote:
A method can refer to private attributes etc. in other objects than 
self.  This is unlike Smalltalk and like C++.  Which objects?  
Obviously, those that _have_ them in the first place.  Does the variable 
used as the invocant, or return value if it is an expression, have to be 
statically typed as being of the identical class?  Or does it apply that 
constraint implicitly at run-time?  If the former, note that in C++ it 
must be the identical class, NOT a derived class, even though that is 
simple to work around, because that is a conceptual point.


A method is defined within a role or class, as is an attribute.  A private 
attribute can generally be referenced only by a method declared in the same 
role or class as said attribute.


A method can reference its own role's/class's private attributes for any 
objects of that role/class, regardless of whether said object is the 
current method call's invocant or not.


If a role or class is composed into another class or is subclassed, the
(for example) subclass can not reference the private attributes of its 
parent class.


As an exception to the above, if a particular class says that it "trusts" a 
particular other class (using "trusts Otherclass;" as a trait), then the 
trusted class can also reference the privates of the first class.


So "trusts" is useful when you have a good reason for certain classes to 
see each other's internals but that they are otherwise private; for 
example, say you're implementing a graph, and you have a separate class to 
define a graph node and the whole graph; those 2 classes are conceptually 
one feature, but are 2 classes because they provide 2 separable interfaces 
to users; the "trusts" lets you do the right thing interface-wise while 
remaining secure without contortions.


Everything I just said ignores the fact that you can always additionally 
make public accessor methods for private attributes, to control/protect 
limited access to them for the general public.


-- Darren Duncan


Re: Conceptual questions about Objects

2008-04-04 Thread Audrey Tang

John M. Dlugosz wrote:

A method can refer to private attributes etc. in other objects than
self. This is unlike Smalltalk and like C++. Which objects? Obviously,
those that _have_ them in the first place.


Correct, though those classes also has to trust the calling class:

class MyClass { has $!attr; trusts YourClass }
class YourClass {
method foo (MyClass $obj) {
$obj!MyClass::attr; # Access to $obj's private attr
}
}


Does the variable used as the invocant, or return value if it is an expression,

> have to be statically typed as being of the identical class?

The $obj above must be evaluated to an object of class MyClass.

AFAICS, the spec doesn't really say if a derived class needs to 
explicitly trust YourClass for it to be used this way:


class MyDerivedClass is MyClass {};
YourClass.foo(MyDerivedClass.new(attr => 1)); # Not sure if this works.


If class C { has $.a; ... }, then I understand that members may refer to
$.a directly but outside of the scope of members defined in the class
they can only be reached by accessors, a() as a method call.


Well, $.a is exactly the same as $(self.a) -- see S12/"are just 
shorthands of C" for the definition.


Methods in class C may call $!a, which is the private accessor method.
Outside the scope, private methods of class C are invisible.


But, it is also stated that in derived and trusted classes, and even in
the class itself, $.a is an accessor call?


Well, $.a is merely shorthand for $(self.a) so derived classes can call 
it just fine.  However in trusted classes, $.a wouldn't make much sense,

as you need to use either $obj.a or $obj!YourClass::a there.


Is this accessor different from the
function form used outside the class? Why keep the variable syntax?


Because it's jolly convenient, especially in interpolated strings, I 
suppose:


say "My position is $.x - $.y - $.z";


I'm getting a picture of 3 forms of access: Really direct, direct but
asking the class to access it rather than knowing how storage works, and
indirect that may involve your own code to do other things besides just
get/set the attribute. But I think the middle one can be handled
invisibly by the compiler -- it's no different from a tied hash.


The middle one is not that different from the first one, because from an 
implementation viewpoint, once YourClass trusts MyClass, then code in 
MyClass might as well have knowledge about how the storage works.



How private is private? I wonder if what you've called private things
are really more like "protected" in C++ (accessible by the derived
class) and that 'my' attributes are really private, as are submethods.
It's all confused. Who is allowed to access what?


No, private methods are not accessible from derived classes, unless the 
base class explicitly trusts them -- See L12/"the exclamation form may 
be used only in the actual class, not in derived classes".


Cheers,
Audrey



Re: Conceptual questions about Objects

2008-04-04 Thread chromatic
On Friday 04 April 2008 13:47:40 John M. Dlugosz wrote:

> But, it is also stated that in derived and trusted classes, and even in
> the class itself, $.a is an accessor call?  As opposed to $!a which is
> the direct access to the attribute.  Is this accessor different from the
> function form used outside the class?

It shouldn't be.

> Why keep the variable syntax? 

Uniform access principle.  See also "Why Java programmers fetishize their 
IDEs, reason #482: autogeneration of metric boat-loads of accessors/mutators 
at just the click of a button."

> I'm getting a picture of 3 forms of access:  Really direct, direct but
> asking the class to access it rather than knowing how storage works, and
> indirect that may involve your own code to do other things besides just
> get/set the attribute.  But I think the middle one can be handled
> invisibly by the compiler -- it's no different from a tied hash.

That really depends on how much external syntax you want to change if you 
change the internal representation of an object.  For me, that's 
approximately none.

-- c