Re: Draft Proposal: Symmetry between Attributes and Accessors
On Fri, Oct 04, 2002 at 04:42:27PM -0700, Michael Lazzaro wrote: [Draft Proposal: Symmetry between Attributes and Accessors] It is proposed that class attributes may be treated as functionally equivalent to an identically named accessor method. In this manner, it shall become irrelevant to callers whether a public attribute of an object is implemented as an attribute, or an lvalue method. Excellent. When Chip was starting Topaz a lot of implementation languages were suggested. Eiffel seemed to have a lot going for it, and this was one of its features that I really liked. The argument, of course, is that the implementation is, well, just an implementation detail and that exposing it to the class user breaks encapsulation. [CONS] - Making publicly accessible attributes at all is considered Bad Form in most OO methodologies, which advocate the use of explicit accessor methods. We may wish to discourage or even prohibit the behavior. If, as a class user, you can't (easily) tell the difference between a method call and an attribute, I don't see any problem. - An attribute and a method are _not_ typically implemented in the same manner. Treating the two as interchangeable might imply runtime overhead. Bah! I bet the internals list will laugh at you :-) -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: Draft Proposal: Symmetry between Attributes and Accessors
At 10:58 AM +0200 10/5/02, Paul Johnson wrote: On Fri, Oct 04, 2002 at 04:42:27PM -0700, Michael Lazzaro wrote: - An attribute and a method are _not_ typically implemented in the same manner. Treating the two as interchangeable might imply runtime overhead. Bah! I bet the internals list will laugh at you :-) will? Nah, we've been laughing for days. ;-P -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Private contracts?
On Friday, October 4, 2002, at 06:23 PM, [EMAIL PROTECTED] wrote: On Fri, Oct 04, 2002 at 09:13:45AM -0400, Chris Dutton wrote: How exactly does one weaken a precondition? At least in Eiffel, if you redefine a method, you may not give it stringer preconditions than the original method, but you may have stronger postconditions. In essence, you're not requiring any more of the client, but you can ensure more to them on completion, thus maintaining the parent's contract. But what does it mean to be stronger? How does Eiffel figure out if a given precondition is stronger or weaker than another? Perhaps an example is the best way to demonstrate this: class FOO creation make feature make(input: SOME_OTHER_CLASS) is require input /= Void do -- something here ensure input /= Void end end -- Good: class BAR inherit FOO redefine make end creation make feature make(input: SOME_OTHER_CLASS) is -- no requirements, weaker precondition do -- yada yada ensure input /= Void old input.some_attribute /= input.some_attribute -- stronger postcondition is ok. end end -- Bad: class BAR inherit FOO redefine make end creation make feature make(input: SOME_OTHER_CLASS) is require input /= Void input.some_attribute = 1 -- requiring more than the parent's make procedure is bad. do -- yada yada -- Not ensuring anything to the client is bad. -- The parent honored that in its contract, so -- the child must also. end end
Re: Private contracts?
On Fri, Oct 04, 2002 at 12:03:44AM -0400, Trey Harris wrote: In a message dated Thu, 3 Oct 2002, John Williams writes: On Thu, 3 Oct 2002, Trey Harris wrote: Incidentally, has there been any headway made on how you DO access multiple classes with the same name, since Larry has (indirectly) promised us that? I.e., I import two classes LinkedList and BTree, both of which define a Node class? Hopefully, LinkedList defines a LinkedList::Node class, and BTree defines a BTree::Node class. Either by explicitly naming them that or by virtue of being defined as an inner class (which might also make it private). Ah, but that's the way you do it now--name the classes differently. (Easy--assuming you control the source code!) In Perl 6, we're supposed to be able to use multiple versions of the same class concurrently, which I think would imply also being able to use multiple classes that happened to be named the same thing. It doesn't imply that. The currently proposed solution is that the true name of a class will include at least the version. But, you can alias classes just like variables: # compile time class Foo is really (Acme::Kung::Foo-1_54); # runtime class Foo := Acme::Kung::Foo-1_54; # (the full classname format hasn't been hashed out yet, this is # just for sake of illustration) So, you could reuse the same short name for multiple different classes, as long as you lexically scoped your aliases. I wouldn't recommend it though, unless you're trying to confuse people. Even in the rare case when you need to use two different versions of the same class in the same code, there will be a clearer way to do it. More useful: keep a site-wide or company-wide file of version aliases to make sure everyone uses the same version, and to make upgrades to the next version as simple as editing a single file. Allison
Re: Private contracts?
In a message dated Sat, 5 Oct 2002, Allison Randal writes: More useful: keep a site-wide or company-wide file of version aliases to make sure everyone uses the same version, and to make upgrades to the next version as simple as editing a single file. Ah, but the usual case is this: You download from CPAN class A that depends on version 1.0 of class N. You then download class B that also depends on version 1.0 of class N. You create an application that uses both classes A and B (and thus N through the dependencies.) Some time later, you discover a bug that requires you to upgrade class B, but the upgrade now depends on class 1.1 of class N. Class A hasn't been upgraded yet, and turns out not to work well with version 1.1 of N. So you need both versions 1.1 and 1.0 of class N running in the application--preferably without having to modify any of your app, class A, or class B. This could be made to work (assuming that classes A and B both specify which version of N they need). Trey
Re: Draft Proposal: Attributes: public vs. private
Dan Sugalski wrote: There won't be any direct access to attributes outside class methods of the class that defines the attributes, unless Larry changes his mind in a big way. (And, honestly, probably not even then) Instead it'll all be accessed via lvalue methods. If an attribute is exposed there's just an lvalue method created, if it's not exposed there isn't. Ack! Hold on, there: I'm being told that Damian thinks lvalues are probably out, and that Larry thinks that pseudo-attributes will be made accessed through the use of lvalues. Please confirm, which is it? I don't particularly care, I just want to write an example down in best-guess form. Now, second question: if slots are in, that means that there is fundamentally no difference between a method and attribute. (This is a Very, Very Good Thing.) Will there be a _syntactic_ difference? e.g. class Zap { # style A attr $sfoo = 5; # scalar attr %kfoo = { key = value }; # hash(?) method sbar { ... code ... }; # method } - vs something like - class Zap { # style B method sfoo = 5;# scalar method kfoo = { key = value }; # hash(?) method sbar { ... code ... }; # method } - or like - class Zap { # style C slot $sfoo = 5; # scalar slot %kfoo = { key = value }; # hash(?) slot $sbar = method { ... code ... }; # method } MikeL
RE: Draft Proposal: Attributes: public vs. private
John Williams: # Personally, I hope they look like attributes. But if they # do, the perl5 # lvalue subs are not the way to do it. Why? Because an # lvalue sub returns # a lvalue which get set _after_ the sub returns. At that # point it is too # late for the sub to do anything useful with the new value. You can do validation in Perl 5 with tied variables (I think), but that's a lot of effort. We could do something related to the old lvalue subs, with optional validation: #Just like Perl 5 method foo() is rw { return $.foo; } #A little different method bar() is rw($new_bar) { if(defined $new_bar) { #yeah, I know, what if $new_bar=undef--maybe exists? validate_bar($new_bar); #Throws an exception if invalid $.bar=$new_bar; } else { $.bar; } } --Brent Dax [EMAIL PROTECTED] @roles=map {Parrot $_} qw(embedding regexen Configure) Wire telegraph is a kind of a very, very long cat. You pull his tail in New York and his head is meowing in Los Angeles. And radio operates exactly the same way. The only difference is that there is no cat. --Albert Einstein (explaining radio)
Re: RFC: [] as the solitary list constructor
On Tue, 24 Sep 2002, Luke Palmer wrote: : =head1 TITLE : : Square brackets are the only list constructor : : =head1 VERSION : : Maintainer: Luke Palmer [EMAIL PROTECTED] : Date: 24 Sep 2002 : Number: 362 (?) : Version: 1 : : =head1 ABSTRACT : : This RFC responds to the fury on perl6-language about the redundancy of : parentheses and brackets with respect to list construction. It proposes : that only brackets may be used to create lists (or arrays), and : parentheses be left for grouping. : : =head1 DESCRIPTION : : Because of the addition of the flattening operator, parentheses in Perl 6, : when used as list constructors, are entirely redundant with brackets. I cringe every time someone says Parens construct lists in Perl 6. Parens don't construct lists in Perl 6. They merely group. The only difference from Perl 5 is that if they happen to group a comma in scalar context, the comma acts differently, not the parens. But the comma acts differently whether or not there are parens. It depends only on the context. I admit that it's difficult to get a comma into scalar context without parens, at least with the current precedence table. But if we swapped the precedence of comma and assignment, it would still be the case that $a = 1,2,3; generates a list because of the comma. The grouping would be implicit. (But there are other problems with doing that.) You can actually do the grouping without parens: $foo = do { 1,2,3 }; Gee, maybe we should get rid of parens, since they're redundant. :-) So the parens have little to do with the list construction. It's all the comma's fault. And in general, parentheses should not be used to construct lists in scalar context. It's better to use [] explicitly. In list context, the [] is not at all the same as (), because () is essentially a no-op in list context, while [] creates an array ref. I suppose we could make comma merely puke in scalar context rather than DWIM, at least optionally. : Additionally, parentheses have one inconsistency which brackets do not: : This is the following case, already shown on perl6-language: : : $a = ();# $a is a list reference with 0 elements : $a = (10); # $a is the scalar 10 : $a = (10, 20); # $a is a list reference with 2 elements : # ... : : If the ability to construct lists with parentheses is removed, so is this : inconsistency. I don't think that's an important inconsistency. : This has the added benefit that there is a significant : visual clue about when a list is being tossed around. This doesn't break : any convenience, just changes the look of it: : : # Perl 6# Perl 5 : [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a) : print *[$a=$b],\n;# print(($a=$b), \n); : push @a: *[1,2,3]; # push @a, (1,2,3); : push @a: [1,2,3]; # push @a, [1,2,3]; I'd rather they just work the way people expect from Perl 5. Requiring people to say *[1,2,3] when they could say 1,2,3 is needless obfuscation. : =head2 Subroutines : : One place of quarrel is subroutine calls. Would this change the argument : list delimiters to brackets? I argue no, because they were never a : parenthesis-delimited list in the first place: : : print(Hello, World, \n); : print Hello, World, \n; : : Thus, in this case, parentheses are used for grouping around the argument : list, not constructing it. Indeed. :-) : The following transformation has been : mentioned: : : print($a, $b); : : is equivilent to : : (print $a, $b); : : so no change is necessary on account of subroutine calls. : : =head2 Semantics : : The semantics of brackets need to be changed slightly to support this. : Specifically, instead of creating a list Ireference, they create a list : Iobject. This object may be stored in an @array interface, or a $scalar : interface. The $scalar interface works the same way as array references : did. But the way @arrays are assigned changes in this manner: : : @array = [1, 2, 3]; # @array has 3 elements, not 1 : @array = [[1, 2, 3]]; # @array has 1 element: an array object : @array[0] = [1, 2, 3]; # same thing : : Slices work as they always have. I think if you're going to replace the whole array using a reference, it's better to use the explicit binding: @array := [1,2,3] It's awfully handy that the right side of a normal list assignment automatically flattens. And it's what Perl 5 programmers expect. They certainly won't expect [] to flatten. : =head2 Hashes : : For consistency, parentheses must be disallowed for hash construction as : well. The same semantic changes apply to braces. This fixes the common : mistake: : : %hash = { a = 1, b = 2 }; : : will now DWIM. Well, that one can be caught, if not the other one. Again, the right approach to dealing with references is probably to bind: %hash := { a = 1, b = 2 };
Re: RFC: [] as the solitary list constructor
According to Larry Wall: I suppose we could make comma merely puke in scalar context rather than DWIM, at least optionally. I rather like Perl 5's scalar comma operator. : $a = ();# $a is a list reference with 0 elements : $a = (10); # $a is the scalar 10 : $a = (10, 20); # $a is a list reference with 2 elements I don't think that's an important inconsistency. What if $a and $b are both array refs, and maintenance programmer changes: for $a, $b { print } to: for $a { print } Will that end up iterating across @$a? The equivalent of that gotcha was forever bugging me in Python (gack). -- Chip Salzenberg - a.k.a. -[EMAIL PROTECTED] It furthers one to have somewhere to go.
Re: Draft Proposal: Attributes: public vs. private
On Friday, October 4, 2002, at 07:39 PM, Michael Lazzaro wrote: [SNIP] Definition: private: A private attribute is an attribute whose scope is restricted such that it may be accessed only within the class in which it has been declared. It is not available to subclasses, nor to code outside the class. [But see an alternative possible definition, below] [SNIP] Note that an alternate definition of private is often used, as follows: A private attribute is an attribute whose scope is restricted such that it may be accessed only within the class in which it has been declared, OR WITHIN ANY CLASS THAT INHERITS FROM THAT CLASS. I'll agree with that. Many programmers in fact expect private attributes to work this way. Some languages recognize all three definitions, calling the above protected access. I'm not sure what languages you are referring to specifically, but if you are including JAVA in that list then you are incorrect because JAVA allows protected members to be accessed from within any class within the same package as well, wether it is a subclass or not. The notion of public attributes is controversial within the OO world. In general, public attributes may be better implemented as public accessor methods to an attribute that remains private. (It typically depends on how the language in question uses attributes, and whether the language treats attributes and methods in a roughly symmetric fashion.) It depends on how you want to encapsulate your implementation details. One of the weakest points of PERL5 is data encapsulation (IMHO). A respectable language should, at its core, enforce a simple, straight forward notion of scoping. So while languages may differ on the types of scoping they offer, the rules and implementations surrounding them should be concise and not open for interpretation. Encapsulation in OO PERL5 provides a multitude of opportunity for people to go out and kill themselves, and anyone else using their code in grand array of variations. Each variation producing its own unique and ghastly crime scene photo op. You have at your disposal such ghastly choices of mayhem as: Encapsulation via closures Tie::SecureHash Encapsulation via scalars...one of my personal masochistic favorites Something as basic as scoping/encapsulation should not be something left up to the programmer to create an implementation of. Nor, should they have the ability to create their own version of it. I'm all for having 16 ways to approach a problem but not when it comes to fundamental language aspects. That degrades the robustness of the language. Two words, 'access modifiers'. :-) OK, so back to the original topic of this thread. I like Java's notion of things. Attributes and methods are package private by default. Which means they are only visible to package they are in (slightly more restrictive then protected). Java also offers the following access modifiers: private - no visibility outside of the class protected - classes in the package and subclasses inside or outside the package public - all classes -Noah
Re: Draft Proposal: Attributes: public vs. private
Note that an alternate definition of private is often used, as follows: A private attribute is an attribute whose scope is restricted such that it may be accessed only within the class in which it has been declared, OR WITHIN ANY CLASS THAT INHERITS FROM THAT CLASS. I'll agree with that. ACK! After re-reading this I about puked. No, that notion of private would not be something I'd agree with :-) That's more like protected. -Noah
Re: RFC: [] as the solitary list constructor
On Saturday, October 5, 2002, at 09:33 PM, Larry Wall wrote: : Additionally, parentheses have one inconsistency which brackets do not: : This is the following case, already shown on perl6-language: : : $a = ();# $a is a list reference with 0 elements : $a = (10); # $a is the scalar 10 : $a = (10, 20); # $a is a list reference with 2 elements : # ... : : If the ability to construct lists with parentheses is removed, so is this : inconsistency. I don't think that's an important inconsistency. [SNIP] : This has the added benefit that there is a significant : visual clue about when a list is being tossed around. This doesn't break : any convenience, just changes the look of it: : : # Perl 6# Perl 5 : [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a) : print *[$a=$b],\n;# print(($a=$b), \n); : push a: *[1,2,3]; # push a, (1,2,3); : push a: [1,2,3]; # push a, [1,2,3]; I'd rather they just work the way people expect from Perl 5. Requiring people to say *[1,2,3] when they could say 1,2,3 is needless obfuscation. I think needless obfuscation is treating $a = (10); as a scalar instead of a list reference containing one item when the rest of the the $a = () are list references. -Noah
RE: RFC: [] as the solitary list constructor
Noah White: # I think needless obfuscation is treating $a = (10); as a # scalar instead # of a list reference containing one item when the rest of the the $a = # () are list references. I think needless obfuscation is treating $a = (10) differently than $a = 10. The latter is the behavior we've come to expect from other languages. This may not look consistent: $a = (10); $a = (10, 20); $a = (10, 20, 30); #... But it is consistent with this: $a = do { 10 }; $a = do { 10, 20 }; $a = do { 10, 20, 30 }; #... (Thanks for pointing that out, Larry.) Parens don't construct lists EVER! They only group elements syntactically. One common use of parens is to surround a comma-separated list, but the *commas* are creating the list, *not* the parens! --Brent Dax [EMAIL PROTECTED] @roles=map {Parrot $_} qw(embedding regexen Configure) Wire telegraph is a kind of a very, very long cat. You pull his tail in New York and his head is meowing in Los Angeles. And radio operates exactly the same way. The only difference is that there is no cat. --Albert Einstein (explaining radio)
Re: Interfaces
On Monday, September 30, 2002, at 08:23 PM, Michael G Schwern wrote: OTOH, Java interfaces have a loophole which is considered a design mistake. An interface can declare some parts of the interface optional and then implementors can decide if they want to implement it or not. The upshot being that if you use a subclass in Java you can't rely on the optional parts being there. Say what?!? I don't think so. If a JAVA class which implements an interface does not declare all of the methods of the interface then that class will be abstract and you won't be able to instantiate a concrete instance of it. You are guaranteed that any concrete instance of a class which implements an interface will contain ALL methods defined by the interface. -Noah
Re: RFC: [] as the solitary list constructor
On Sunday, October 6, 2002, at 01:50 AM, Brent Dax wrote: Parens don't construct lists EVER! They only group elements syntactically. One common use of parens is to surround a comma-separated list, but the *commas* are creating the list, *not* the parens! Following this rule would mean that $a = (); # $a is a list reference with 0 elements should not be a list reference at all and would appear inconsistent. -Noah