Larry Wall writes: > Perl 5 always makes a copy of return values, but that just turns > out to not matter for references, since a copy of a reference is as > good as the original reference. Perl 5 also propagates scalar/list > context into subs. For $:foo it doesn't matter--it always behaves > as a scalar value even in list context. In list context, @:bar and > %:baz should probably return copies of their values much like they > do in Perl 5, (or more likely, some kind of lazy COW reference that > can lazily interpolate into the surrounding lazy list context). > Whether $self.:bar and $self.:baz should behave the same is an > interesting question. They *look* scalar, so maybe they should imply > reference return, and you'd have to say > > return $self.:bar[]; > return $self.:baz{};
I'll just point out, the rest of this message, with all the autocopy complexity (according to /some/ people), uses this assumption. It all happily goes away if $self.:bar returns a list if @:bar is declared. And I can't, off hand, see any other problems with it. Maybe I'm just blind, though. Luke > to get the equivalent of > > return @:bar; > return %:baz; > > But bare > > return $self.:bar; > return $self.:baz; > > would be equivalent to: > > return \@:bar; > return \%:baz; > > But I could argue it the other way too. > > : For each, will the calling code be able to > : modify $obj's attributes by modifying the return values, or not? > > The caller can modify the value only if an explicit ref is returned (or > the accessor is marked "rw"). > > Where we seem to differ from Perl 5 is that in scalar context, a bare > array or hash automatically enreferences itself rather than returning > some kind of size. So in scalar context, it would seem that > > return @:bar; > return %:baz; > > and > > return $self.:bar; > return $self.:baz; > > are equivalent to: > > return \@:bar; > return \%:baz; > > (Again, $:foo is never a problem unless it's already a reference.) > > So the issue is whether this interpretation will encourage people to > accidentally > return references to things they didn't want to give write access to. On the > other hand, making the private methods context sensitive doesn't actually > seem to fix this particular problem, but just pushes it down one level into > the implicit accessor. Maybe we need to work something up where > references returned from read-only accessors are always COW references. > If we assume that [...] is lazy when it can be, then that would be saying that > scalar context forces > > return @:bar; > > to mean > > return [@:bar]; > > and you'd have to write an explicit > > return \@:bar; > > to get around that. But that seems kind of hacky and special-casey. > > On the other hand, there are going to be strong cultural forces > discouraging people from writing such accessors in the first place, > so maybe we just go ahead and let people return hard refs in scalar > context on the assumption they know what they're doing. I suspect > that most actual accessors to arrays and hashes will just look like > ordinary getter and setter methods with extra args for subscripts, or > will return an explicit proxy if they want to behave like an lvalue. > And in either of those cases, you don't try to return the entire > array or hash. So maybe we should settle for the clean but slightly > dangerous semantics here. > > Except that we've defined default read-only accessors that would, > under the "clean" rules, give people automatic access to arrays and > hashes if called in scalar context. So I think we really only have > three options here for the public accessors: > > Don't generate autogenerate accessors at all for arrays and hashes. > Generate array and hash accessors that refuse to work in scalar context. > Generate array and hash accessors that autocopy in scalar context. > > Of those three, the last seems the most friendly. > > : Going further, what is the exact syntax for each type of attribute to > : specify whether a copy or a reference is returned? > : > : In Perl 5, with the latter two, the difference was a "return $bar" vs > : "return [EMAIL PROTECTED]" for reference vs copy. I would like that Perl 6 > : is also at least as clearly disambiguated. > > If we go "dwimmy" rather than "clean", and assume private array and > hash accessors always return refs, then these return refs from public > accessors: > > return \$self.:foo; # in any context > return $self.:bar; # in any context > return $self.:baz; # in any context > return \$:foo; # in any context > return \@:bar; # in any context > return \%:baz; # in any context > > and these return copies: > > return $self.:foo # in any context > return $self.:bar[]; # in list context > return $self.:baz{}; # in list context > return $:foo; # in any context > return @:bar; # in any context > return %:baz; # in any context > > That's actually simpler than the tables I made up when I was believin in > the "clean" solution. What it essentially boils down to is that return > from a public accessor always forces list context on its arguments even > if the accessor was called in scalar context (in which case a ref to > a COW list is stored in the scalar). > > I'm wondering if we should just up and say that "return" always forces list > context on its arguments. It would simplify some things, and complicate > others... > > : Note that specifying this in the attribute definition isn't > : appropriate, since an attribute could just as easily be an array of > : arrays, or hash of hashes, and I am returning an inner array or hash > : that I either do or don't want to be modifiable by calling code. > > Yes, even with the return context hack, it'd only go one level down. > I think at some point we have to rely on people not to write stupid > accessors, and rely on culture to enforce that. I really, really > want to avoid falling into C++ const hell. > > Maybe we can define some kind of deepcow operator for the nested cases. > Or maybe there's some other solution I don't see yet, or that someone has > already told me about and I've forgotten... > > : Separate question, just to confirm, I assume that plain '=' always does a > : copy? > > Yes. And with := it's mandatory for "is copy" parameters, optional > for "is constant" parameters, and prohibited for "is rw" parameters. > > Hopefully if values come back COW from a routine, we can avoid a > duplicate copy on the assignment. > > : Thank you for any clarification. > > Well, I don't know if I clarified it that much, but you're welcome > to the mud too. :-) > > Larry >