Re: Stupid Newbie Question
On Thu, Nov 15, 2001 at 05:49:34PM -0800, John Rudd wrote: So, for example, lets say I have an object $foo, which is an instance of Class A. In one method, foo tries to access an instance variable of $bar, an instance of Class B (not inherited from Class A). This is a naughty thing to do. $bar should have a set of accessor methods if you're really worried. Read on. If $bar's instance variables are somehow hidden Looks like the whole an object is just a hash reference paradigm might be mutating some to allow better data hiding. There was a big thread on perl6-language about this just recently. I could then have the Class B auto(vivify|glob) routine perform checks on the identity and heritage of $foo, and then decide what to do about the request. There's a whole host of modules that make writing accessors cheap, Class::Accessor and Class::Struct for example. Once you're inside an accessor method you can do whatever access checking you like. If I'm reading the tea leaves correctly, Perl 6 will address this sort of thing with some variation on slots. So you can declare for *this* list of instance variables, make me some simple accessors. So C$foo-bar = 'this' == C$foo-{bar} = 'this'. So rather than using AUTOVIVIFIY you'd use slots and accessor methods. In theory, these slots should be closer to the speed of a regular hash than accessor methods currently are in perl5. That way you could choose to impliment Smalltalk or C++ style protections (public, private, protected, etc) Last I checked Smalltalk had no privacy protection. So, for Smalltalk type semantics, if $foo != $bar, the request will throw some sort of exeption indicating that $foo isn't allowed to see $bar's instance variables. But, if $foo == $bar, then the actual value will be found and returned. Smalltalk? not allowed? You sure about that? Or is this something you hacked together with doesNotExist? The question in my brain, since I don't know perl's internals in very much detail, is how hard is it to figure out who the caller was? caller(). Or is something more involved? It's not just a matter of knowing what package the invoking subroutine belonged to, because instances of the same class might have have access to eachother's instance variables (ala Smalltalk). It further complicates things if you want to extend it to include C++ style friend functions (I don't, but others might). die Sorry, private method unless caller eq ref $self; die Sorry, protected method unless caller-isa(ref $self); die Sorry, you're not my friend unless exists $self-{_my_friends}{caller()}; That about covers basic method privacy. (yes, I know you can emulate class variables via package globals like $Class::blah, but I'm trying to look at it in a more uniform point of view so that you can fully treat Classes themselves as being objects) Class::Data::Inheritable anyone? :) -- Michael G. Schwern [EMAIL PROTECTED]http://www.pobox.com/~schwern/ Perl Quality Assurance [EMAIL PROTECTED] Kwalitee Is Job One You killed my fish? Why does that pickle you? http://sluggy.com/d/010204.html
Re: Stupid Newbie Question
On Thu, Nov 08, 2001 at 03:56:59PM -0800, John Rudd wrote: So, I'm reading various things about lots of changes for perl6, and some arcane things going away, and stuff like that.. and I suddenly wondered if one of my favorite features of Perl Objects (the one that keeps me from migrating to tcl or python, cuz I can never find clear information about whether such an analog exists in those languages) is going away: AUTOLOAD. Going away? No way, it's SPREADING! We might wind up with AUTOGLOB, too. http://dev.perl.org/rfc/324.pod -- Michael G. Schwern [EMAIL PROTECTED]http://www.pobox.com/~schwern/ Perl6 Quality Assurance [EMAIL PROTECTED] Kwalitee Is Job One List context isn't dangerous. Misquoting Gibson is dangerous. -- Ziggy
Re: Stupid Newbie Question
On Thu, Nov 08, 2001 at 04:21:57PM -0800, John Rudd wrote: So, does this mean my other heart's desire of operator overloading might be coming forth? Yeah, that was mentioned in Apoc and Exewhatever 3. -- Michael G. Schwern [EMAIL PROTECTED]http://www.pobox.com/~schwern/ Perl6 Quality Assurance [EMAIL PROTECTED] Kwalitee Is Job One We're talkin' to you, weaselnuts. http://www.goats.com/archive/000831.html
Re: RFC from a newbie: Method References
On Fri, Dec 15, 2000 at 11:23:23PM -0800, Ian Hickson wrote: Having said that: The only feature that I really miss from Perl 5 is the lack of method pointers -- that is, references to functions in a package with an associated object. Oh, that's easy. Use a closure... my $foo = Foo-new; my $meth_ref = sub { $foo-method }; $methodref(); In fact, here's an example implementation... package Class::MethRef; use strict; sub meth_ref { my($proto, $method, @args) = @_; return sub { $proto-$method(@args) }; } So this... my $meth_ref = $obj-meth_ref('foo', @some_stuff); $meth_ref-(); is equivalent to this.. $obj-foo(@some_stuff); You could even make the meth_ref take additional (or overriding) arguments. Its a good idea, I'll put Class::MethRef on CPAN soon. -- Michael G. Schwern [EMAIL PROTECTED]http://www.pobox.com/~schwern/
Re: RFC 163 (v2) Objects: Autoaccessors for object data structures
On Mon, Sep 18, 2000 at 04:58:45AM -, Perl6 RFC Librarian wrote: =head2 Combining attributes You can, of course, combined the C:laccess and C:raccess attributes on a given key to autogenerate accessors that work in both Clvalue and Crvalue contexts, if you simply want to hide your data. How about also just ":access" to do both? It would seem to be the most common case. =head2 Mixing autoaccessors and real subs The final case is where these become really powerful, but also makes the implementation a little tricky. Here, we want to create an lvalue sub that does something productive, but an rvalue autoaccessor: I really don't see how this is necessary. If you have to write a custom accessor, you might as well write the whole thing. Doesn't save much programming effort to be able to still use the default for one context and custom for other, and it would greatly simplify the implementation without it. I also don't see that the optimization of one half of the accessor vs the other is worth the trouble. =head1 IMPLEMENTATION In order for this to work, a couple things have to be true: 1. Autoaccessor methods have to take precedence over declared methods in some way. 2. A means for duplication of method namespace has to exist. If we eliminate the thing about mixing, this goes away. 4. There must be a way to set attributes on individual hash keys in Perl 6. While in general this might be a good idea, is it really necessary for this proposal? How about this: package Foo; use laccess qw(this); use raccess qw(foo); use access qw(up); sub new { bless {} } my $foo = Foo-new; $foo-this = 'that'; $foo-foo('bar'); $foo-up = 'down'; $foo-up('sideways'); This also means accessors are defined on a per class basis rather than per object (which is potentially extremely confusing and difficult to implement). Although this makes your C$self-{DATA}-{NUMERIC}-{S_size} :raccess('size') = undef; case tricky to emulate. It also makes combining attributes difficult. Will ponder. Bingo. So, implementationally, it seems all of these could be satisfied by having this: $r-method; Do the following in order: 1. Look for a declared autoaccessor for the given context. Context. I hope this means context of the object $r? 2. readonly rvalue subs http://www.mail-archive.com/perl6-language-objects@perl.org/msg00096.html implies that this isn't needed because of the proposed :constant hash attribute. This isn't enough. There is a distince difference between an attribute that is constant, and one which is read-only. That difference being that a read-only value should be able to be written to *privately*. Consider the case of an accessor which returns a list of object fields which have changed since the last time the object was changed (Class::DBI does this). The list of obviously not constant, yet the accessor should be read-only. 3. mutators I suspect the first one should not be solved. The real idea behind autoaccessors, as James pointed out, is speed and simplicity. As such, requiring you to pass stuff around by reference: $r-autoaccessor = \@stuff; $r-autoaccessor(\@stuff); @stuff = @{$r-autoaccessor}; I was about to say that :deref wouldn't be a bad idea, but that would just be shifting the problem from pass-by-reference to pass-by-value. $r-autoaccessor = @stuff; @stuff = $r-autoaccessor; If this is made equivalent to your code above, it makes pass-by-value icky. $r-autoaccessor = @{[@stuff]}; If we make it copy the value of @stuff first (like $r-autoaccessor = [@stuff] currently does) then this all encourages inefficiencies. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse GuRuThuG make a channel called Perl, and infest it with joking and funit doesnt make alot of sense.
Re: RFC 163 (v2) Objects: Autoaccessors for object data structures
On Sun, Sep 17, 2000 at 11:25:49PM -0700, Nathan Wiger wrote: I also don't see that the optimization of one half of the accessor vs the other is worth the trouble. Well, it depends on how much faster the autoaccessor is. If it is much faster, and you need to access a whole bunch of data repeatedly, then this makes sense. But if the autoaccessor is about the same as a sub speed-wise, then screw it, I agree. I dunno, its going to be alot of work for an optimization. Hell, if you implement that, you might as well go all the way and implement polymorphic functions. 2. readonly rvalue subs http://www.mail-archive.com/perl6-language-objects@perl.org/msg00096.html implies that this isn't needed because of the proposed :constant hash attribute. This isn't enough. Yeah, check out this email: http://www.mail-archive.com/perl6-language-objects@perl.org/msg00099.html The idea I originally had was that :raccess would specify something was an rvalue accessor which only returned a value, and couldn't take arguments. I think this is probably the way to go, otherwise we have to start adding other keywords, properties, etc, which really complicate things too much. Saw that email, its not enough. The usefulness of an automated accessor is hamstrung if you can only get with it and never set. The vast majority of cases wil be read/write. You need not have :raccess, :rvalue, :laccess and :lvalue. Just :raccess, :rvalue and :readonly (not :ronly, looks like :rightonly). For an idea of how complicated this can all get, look at Class::MethodMaker. Has a *bewildering* array of options. What you've got so far looks down right boney by comparison. Couldn't quite see what you were getting at here - maybe a little clarification. I'm pretty sure I understand ("autoderef bad, but forced copy bad too") but want to make 100% sure. That's about it. *grunt* -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Plus I remember being impressed with Ada because you could write an infinite loop without a faked up condition. The idea being that in Ada the typical infinite loop would be normally be terminated by detonation. -- Larry Wall in [EMAIL PROTECTED]
Re: RFC 254 (v1) Class Collections: Provide the ability to overload classes
On Mon, Sep 18, 2000 at 05:49:28AM -, Perl6 RFC Librarian wrote: Here's where the problem lies. Even though we now have a subclass of Frog, the Forest class is still referencing the original Frog class and not Frog::Japanese. The DBI has this very problem! DBI-connect() returns DBI::db objects, DBI-prepare() returns DBI::st. If you want to override the behavior for statement handles and connections, its not enough to just subclass DBI::st and DBI::db, you must also subclass DBI and override connect() and prepare() (and hope DBI doesn't use DBI::st or DBI::db anywhere else.) DBI-init_rootclass() is a fairly hairy workaround to this problem. It works like this: package Ima::DBI::db; @ISA = qw(DBI::db); package Ima::DBI::st; @ISA = qw(DBI::st); package Ima::DBI; use base qw(DBI); Ima::DBI-init_rootclass; # $dbh is an Ima::DBI::db object, $sth is an Ima::DBI::st $dbh = Ima::DBI-connect(...); $sth = $dbh-prepare(...); Ima::DBI-init_rootclass() informs the DBI that Ima::DBI is a subclass and that Ima::DBI::db and Ima::DBI::st objects should be used. It does this by just appending '::db' onto the classname, which means the names of the classes are fixed. A Bad Thing. [From DBI-connect()] # XXX this is inelegant but practical in the short term, sigh. if ($installed_rootclass{$class}) { $dbh-{RootClass} = $class; bless $dbh = $class.'::db'; my ($outer, $inner) = DBI::_handles($dbh); bless $inner = $class.'::db'; } It works, but to quote Tim Bunce there... *sigh*. So anyhow, yes, this is a big, icky problem. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse mendel ScHWeRnsChweRNsChWErN SchweRN SCHWErNSChwERnsCHwERN sChWErn ScHWeRn schweRn sCHWErN schWeRn scHWeRN SchWeRN scHWErn SchwErn scHWErn ScHweRN sChwern scHWerNscHWeRn scHWerNScHwerN SChWeRN scHWeRn SchwERNschwERnSCHwern sCHWErN SCHWErN sChWeRn
Re: RFC 218 (v1) Cmy Dog $spot is just an assertion
On Mon, Sep 18, 2000 at 09:48:27AM +0100, Piers Cawley wrote: Michael G Schwern [EMAIL PROTECTED] writes: Nope. fields::new() basically just does Cbless [\%{"$class\::FIELDS"}], $class, but the current pseudohash implementation doesn't care if something is an object or not. It just cares about either A) its type or B) what's in $ph-[0]. Hmm... it still feels like undocumented behaviour. I'd definitely be inclined to tighten up the base/fields behaviour. My feeling is that the proposal makes them closer to the Right Thing. Its plenty documented. But if we simply put a bullet into pseudo-hashes, as per RFC 241, this all goes away. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse But why? It's such a well designed cesspool of C++ code. Why wouldn't you want to hack mozilla? -- Ziggy
Re: RFC - Interpolation of method calls
On Mon, Sep 18, 2000 at 07:23:41AM -0600, Tom Christiansen wrote: Oh joy: now Perl has nested quotes. I *hate* nested quotes. Those are single-quotes inside double-quotes. Yep: nested, with varying semantic effects. Completely nasty. As Nate pointed out: print "$hash-{'f'.'oo'}" already works fine and the world spins on. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse But why? It's such a well designed cesspool of C++ code. Why wouldn't you want to hack mozilla? -- Ziggy
Re: RFC 163 (v2) Objects: Autoaccessors for object data structures
On Mon, Sep 18, 2000 at 01:02:31PM -0700, Glenn Linderman wrote: OK, thanks for the info. I'm not an internals guy, but I guess I should have written the benchmark. It just _seemed_ they should be slower, because there is more work to do the hashing. The actual lookup, I agree, should be the same. Similar mistaken logic leads to "globals are faster than lexicals". Now while it is _totally_ true from your numbers that the lookup (read reference) costs are the same, it would seem that the variability in write references could still make this pay off. The set_const is about 40% slower for hash, and set_var is about 166% slower. Accessor overhead swamps all. N.B. I wonder if the hash accessor is faster because the array accessor is referencing past the end of the array? (not apples to apples here, you use index 0 everywhere else, and index 1 in the accessor.) Its just benchmarking flutter. I reran it with 1 everywhere else and the same results. Besides, because $aobj is global, the first call would extend the array and the following 899_999 wouldn't worrry about it. I know, lets call it a pseudo-hash! Been there, done that, worn the scars proudly. Is _that_ what a pseudo-hash is? Then it sounds like a good idea. But maybe there are some differences between today's pseudo-hash and my proposal, even though they might be similar. I think mine is pretty general, and the discussion on this list made it sound like pseudo-hash has some other restrictions? Read RFC 241 for a brief overview of pseudo-hash problems. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Sometimes these hairstyles are exaggerated beyond the laws of physics - Unknown narrator speaking about Anime
Re: RFC 163 (v2) Objects: Autoaccessors for object data structures
On Mon, Sep 18, 2000 at 01:26:45PM -0700, Glenn Linderman wrote: Michael G Schwern wrote: Similar mistaken logic leads to "globals are faster than lexicals". Maybe so, but I'd think lexicals would be faster, because more of the lookup is done at compile time rather than runtime... so I'm not sure what is similar about the mistaken logic... A better one would be "dereferences are slower than using the variable directly". ie. its a common misconception that $href-{key} should be slower than $hash{key} because you have to dereference $href. This mostly comes from C where dereferencing a pointer is slower than using the variable directly. Turns out references edge out globals. Why? A global variable has to look up its symbol at run-time, get a *reference* out of it and dereference it. Most of the time if you're using a reference, its lexical. All a lexical reference has to do is dereference itself, thus avoiding the symbol table lookup. I've see this done: sub foo { my($href) = shift; local(*hash) = $href; } as an "optimization". Turns out that slows things down even further! Declaring the local version of %hash is much, much more work than everything else altogether. I guess I'm trying to say something about micro-optmizations being more trouble than they're worth and usually hurt more than they help. So let's posit you've cured the accessor overhead problem. Now we're left with set_const being 40% slower for hash, and set_var 166% slower for hash. Still want to ignore it? Why? Well, the fixed accessors would be using constant key lookups, so we only have to worry about 40%, and this is 40% of a tiny, tiny fraction of the actual overhead of a typical class. So going nuts about making it faster probably won't gain us much overall. Certainly not worth the effort of making arrays as easy to use as objects. Take a class you've written that uses thin accessors and run it through a profiler. Look at the time spent in the accessors and reduce it by 80% (the expected efficiency increase for built-in accessors) and recalculate its overall effect on your performance. If its more than 5% I would be surprised. Bascially, if accessor methods are currently eating less than 25% of your total overhead, they will eat 5% if they are made built-in. After that, diminishing returns kicks in. A further 40% reduction results in a 2% overall increase. Who cares? Spend the time elsewhere. (This is the classic argument against early/micro optimizations) I know, lets call it a pseudo-hash! Been there, done that, worn the scars proudly. Is _that_ what a pseudo-hash is? Then it sounds like a good idea. Yeah, it *sounds* like a good idea, but there's lots and lots of little problems. Doesn't play well with multiple inheritance I can sure believe this. There'd be indexes from multiple base classes. I don't know how Perl does multiple inheritance anyway, so I can't comment effectively on whether this is or would be a problem. If Perl does multiple inheritance, I haven't stumbled across the documentation for it, but neither have I looked. I don't use multiple inheritance. The phrase "multiple inheritance" only comes up in perlboot, perltoot and perltootc. perlobj only implies that MI works because otherwise it would be $ISA, not @ISA. I use MI alot and really couldn't see a language without it. Muddles the behavior of typed variables Not sure what this means. Currently, the only thing really using the Cmy Dog $spot syntax is psuedo-hashes. my Dog $ph; $ph-{cat} = 'Mrs. Chippy'; # $ph-[$Dog::FIELDS{cat}] and there have been several RFCs about clarifying what typed variables mean (usually in reference to objects). Pseudo-hashes get in the way of alot of those proposals. Requires significant extra documentation and complication of hash operations. I've used perl for some years, and never noticed pseudo-hashes from the user perspective. Is this an internals only issue? Or what else have I missed? Its both an internals and a doc issue. In the guts, there's a bunch of special cases for them in the guts (though not nearly so troublesome as, say, threading) although most of the functionality is restriected to av.c. The documentation is the bigger issue, pseudo-hashes involve alot of caveats when explaining hashes, though much of them have gone away in 5.6.0. Also, the whole fields and base modules are troublesome. If you wish to write a subclass but use a pseudohash for your object instead of a hash, you really can't unless the class author was careful enough to declare all their fields (a rare occurance). Also, consider the case of a pseudo-hash friendly class, but with a subclass that uses @ISA directly instead of base.pm and hashes instead of pseudo-hashes. A subclass of that subclas
Re: RFC - Interpolation of method calls
Sorry, I wasn't subscribed to perl6-language-objects and didn't even realize there was a discussion going on. I just fixed that. I didn't mean to hijack RFC 103, I can't remember if I'd even looked at it before... but Nathan seems okay with that and it is a deceptively large issue. Version 2 of the RFC went out last night (I'll have to do v3 after reading these comments) and clarifies a few things (the changes are all listed at the top). Most importantly, C"$weather-temp("F")" was a typo. It should have been C"$weather-temp(\"F\")". Also, RFCs about interpolation of class methods and subroutines also went out last night, so I'll let them speak for themselves. Now, about that context thing. The main conundrum is what to do with methods that return a list. Would it be best to just let it be scalar context? # $inventory-pinatas returns a list of pinatas we have. # "Yes, El Guapo, I would say I have 23 pinatas\n"; print "Yes, El Guapo, I would say I have $inventory-pinatas pinatas\n"; Or would it be better to expand the returned list, as arrays are expanded with Cjoin $", @array? Now that I think about it, its fairly obvious that simple scalar context is best. Why? I can't even think of a useful example of the list expansion. Most of the time you want to seperate them with a ", " anyway, not with $". So junk that bit about the context weirdness. Simple scalar context it is. Nathan already covered the questions about evaluating expressions and arguments. Perl already does it for everything else. Furthermore, interpolating the expression should be simple, as I realized later while writing the RFC for interpolatoin of subroutines. The tokenizer can watch for /[A-Z_]\w*/i. If followed by a '(', then the parsing becomes the same as for normal subroutine arguments excepting that it must watch for an unescaped closing string character. I'm also glad to find out Perl already disallows whitespace for other interpolated constructs. I appear to have a new version of the RFC ready without the first even having made it out to the public! -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Many people think that an UFO is probably propelled by some kind of antigravity magnetic motor. I have a totally different thinking. I believe that an UFO is propelled by jet engine. UFO's gyroscopic body rotates and serves as its wing to keep UFO's body balanced in the air. --Alex Chiu, Immortality Guy
Re: RFC - Interpolation of method calls
On Sun, Sep 17, 2000 at 08:56:23PM -0600, Tom Christiansen wrote: While you're there, you should fix it to spell piƱatas properly. :-( We're not talking about stands of pine trees, presumably. Funny, I know how to type extended characters in MacOS, but I have no idea how to do it in X. Hell, my font doesn't even display them right. *grumble* -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse BOFH excuse #270: Someone has messed up the kernel pointers
Re: RFC 222 (v1) Interpolation of method calls
On Thu, Sep 14, 2000 at 05:31:44PM -0500, David L. Nicol wrote: A possibility that does not appear in RFC222.1 is to put tho whole accessor expression inside curlies: print "Today's weather will be ${weather-temp} degrees and sunny."; which would follow the "You want something funny in your interpolated scalar's name or reference, you put it in curlies" rule. Since the contents of that expression is not strictly \w+ it does not get interpreted as the symbol table lookup ${'weather-temp'}, so that is not a problem, nor are the whitespace situations listed in the CAVEATS section. Could you write up some practical examples where this might be useful (slapping whitespace between the - and method name isn't practical or useful). I'm loathe to muddle the meaning of ${bareword}. It did make me think of something else. What about by-variable method calls. That is: my $meth = 'species'; print "How much is that $pet-$meth() in the window?"; This should deparse to: my $meth = 'species'; print "How much is that ".$pet-$meth()." in the window?"; -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse I'm not cute, I'm evil. -- Diablo www.goats.com
RFC - Interpolation of method calls
=head1 TITLE Interpolation of method calls =head1 VERSION Maintainer: Michael G Schwern [EMAIL PROTECTED] Date: 14 Sep 2000 Version:1 Mailing List: [EMAIL PROTECTED] =head1 ABSTRACT Method calls should interpolate in double-quoted strings, and similar locations. print "Today's weather will be $weather-temp degrees and sunny."; Would deparse to: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; =head1 DESCRIPTION =head2 The Current Problem With OO Interpolation Object-oriented programming encourages data-hiding, and one of the most basic tool for this is the accessor method. For reasons which should be obvious, C$obj-foo() is usually better than C$obj-{foo}. However, there are several barriers to using an accessor method as simply as one does a hash lookup. Other RFCs deal with most of the current issues, but a basic one still remains. print "Today's weather will be $weather-temp degrees and sunny."; This does not DWIM. Instead of interpolating C$weather-temp as a method call, it comes out as C$weather.'-temp' and is usually followed immediately by the question "What does 'Weather=HASH(0x80d4174)-temp' mean??" Most programmers learning OO Perl expect this to work and are surprised to find that it does not. Work arounds abound: # If I wanted printf(), I'd have written it in C. printf "Today's weather will be %d degrees and sunny.", $weather-temp; my $temp = $weather-temp; print "Today's weather will be $temp degrees and sunny."; print "Today's weather will be @{[$weather-temp]} degrees and sunny."; print "Today's weather will be ".$weather-temp." degrees and sunny."; None are as simple and as obvious as: print "Today's weather will be $weather-{temp} degrees and sunny."; and because of this users groan at having to use accessor methods and are often tempted to violate encapsulation for ease of use. =head2 Proposed Solution - Interpolate Methods Therefore, it is proposed that direct object method calls be interpolated inside double quoted strings and similar constructs. print "Today's weather will be $weather-temp degrees and sunny."; should parse out as: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; thus returning DWIMness to methods and strings and removing one barrier to accessor method's acceptance over hash lookups for objects. Methods will be run in scalar context. A method which returns a single scalar is treated normally. If a list is returned, it should be treated same as array interpolation. The list seperator will be applied. In effect, the deparsing will really work out as follows: print 'Today\'s weather will be '.join($", $weather-temp()). ' degrees and sunny.'; However if temp() calls wantarray(), the result will be FALSE (scalar). (For the remainder of the RFC, the join() will be assumed when discussing deparsing for brevity.) Should it be decided that a formal distinction be made between accessor methods and other types (RFC 95), method interpolation should interpolate Bany method. =head2 Argument passing Interpolation should also handle passing arguments to methods in a string: print "Today's weather will be $weather-temp("F") degrees and sunny."; This should deparse to: print 'Today\'s weather will be '.$weather-temp("F"). ' degrees and sunny.'; The arguments to the method are considered as normal expressions, thus: print "There is $obj-foo(this = $yar, that = 2 + 2) in my head."; deparses as: print 'There is '.$obj-foo(this = $yar, that = 2 + 2). ' in my head."; =head1 CAVEATS Indirect object syntax, being already ambiguous, cannot be easily be distinguished in a string from normal text and should not be interpolated. This is ok, since accessors are rarely called with indirect object syntax. Are there any contexts besides double quotes ("", qq{}, "EOF") where this need be applied? What about inside regexes? And if so, left and/or right hand side? Normally, whitespace is allowed between tokens of a method call. $obj - bar ("this"); and $obj-bar("this"); are equivalent. Whitespace between the object, '-', method name and opening paren should be disallowed when interpolated. This will avoid many ambiguous cases. Should the method not exist, Perl will throw an exception/die as usual. C"$var-{this}[2]{is}-{complex}-method" should also be interpolated. Also C"$obj-method-{key}" for the case where a method returns a reference. =head1 IMPLEMENTATION The behavor of the parser to check for embedded variables would have to be altered, namely the case where an embedded variable is being dereferenced. A case would be added to allo
Re: RFC 218 (v1) Cmy Dog $spot is just an assertion
On Thu, Sep 14, 2000 at 02:19:38PM +0100, Piers Cawley wrote: Michael G Schwern [EMAIL PROTECTED] writes: package Dog; use fields qw(this night up); my Dog $ph = []; $ph-{this} = "that"; That works? I thought you had to do: my Dog $self = fields::new('Dog'); Nope. fields::new() basically just does Cbless [\%{"$class\::FIELDS"}], $class, but the current pseudohash implementation doesn't care if something is an object or not. It just cares about either A) its type or B) what's in $ph-[0]. I don't know if this is a good thing or a bad thing, but there's nothing on the table to change it (yet). my Dog $ph = []; $ph-{this} = "that"; deparses at compile-time to: my Dog $ph = []; $ph-[$Dog::FIELDS{this}] = "that"; # actually the %FIELDS lookup is also # done at compile time, but I left # it in for illustration. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Sometimes these hairstyles are exaggerated beyond the laws of physics - Unknown narrator speaking about Anime
Re: RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
So I thought of a serious problem with part of this RFC. The bit about using indirect object syntax... Instead, this RFC proposes that Ctie's operation become much more fundamental, simply translating functions via the existing indirect object syntax: tie Transaction %trans;# indirect object constructor $trans{$var} = $value ;# $obj-STORE($var, $value); lock $trans{$var}; # $obj-lock($var); There's a nasty inconsistency there. Consider the following. package Foo; sub lock { flock $_[0], LOCK_EX; } lock $trans{$var}; Normally, the Foo::lock() subroutine in the current package will be called. However, if %trans is a tied hash to a class which defines a lock() method (let's call it Lock::Ness) the meaning of the program radically and unexpectedly changes. Instead of CFoo::lock($trans{$var}), we now have C$obj-lock($var) and the two routines can do something *completely* different. This might have been your intention, to override the lock(0 function, but it becomes extremely dangerous when you consider the effect of a tied variable on interal code. You pass in a tied hash to a module and somewhere deep in its guts it calls the function foo() on it, but you have foo() defined as a method and your foo() has absolutly nothing to do with their foo() causing havoc. Action at a distance. The only possible recovery I can see is for the function currently in scope to have a higher "precedence" than the tied method. So in our example, the call to lock() remains a call to Foo::lock() and not to the tied method. The reverse situation, that of a tied method being accidentally turned into a function call, shouldn't happen in normal circumstances. Only problem is, reversing the precedence makes it near worthless. Read on. I just thought of a more fundemental problem. Looking at the rationale for this... Plus, if you want to support extra methods of your own, you must mix object and tied calls: $obj = tie %trans, 'Transaction'; $trans{$var} = $value; $obj-lock($var); Unfortunately, this defeats one of the key purposes of tie, which is OO transparency. And, creating a class that supports both OO and tied interfaces is difficult, requiring typeglobs or duplicate handler functions. Instead, this RFC proposes that Ctie's operation become much more fundamental, simply translating functions via the existing indirect object syntax: tie Transaction %trans;# indirect object constructor $trans{$var} = $value ;# $obj-STORE($var, $value); lock $trans{$var}; # $obj-lock($var); delete $trans{$var}; # $obj-delete($stuff); foo %trans;# $obj-foo; The idea is that by using the indirect object syntax, the tied variable can call methods on itself beyond those which are built in. But this doesn't really win you much besides some syntactic sugar. Consider this code: lock $trans{$var}; What if %trans is not tied? Then a lock() subroutine would have to be in scope, which presumably you've exported as part of your tied module. But that means you have to write function wrappers around your methods, which is even more work than the simple method aliasing for the OO/tie hybrid. And in the case of locking a key in a hash, you can't do it because lock() will receive the value. If the code is intended to be run *only* on tied variables, then you could have just used a plain object and dropped the sugar. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Plus I remember being impressed with Ada because you could write an infinite loop without a faked up condition. The idea being that in Ada the typical infinite loop would be normally be terminated by detonation. -- Larry Wall in [EMAIL PROTECTED]
Re: RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
On Sun, Sep 10, 2000 at 04:00:30PM -0700, Nathan Wiger wrote: Normally, the Foo::lock() subroutine in the current package will be called. However, if %trans is a tied hash to a class which defines a lock() method (let's call it Lock::Ness) the meaning of the program radically and unexpectedly changes. That's true. However, this is actually no different than the situation currently with blessed objects. If the code was rewritten: sub lock { print "Hello!" } $trans = new Lock::Ness; # ;-) lock $trans; # $trans-lock The lock method from the $trans object would be called, even though there was a main::lock, because of the higher precedence and binding of indirect objects. That's not right. package Lock::Ness; sub lock { print "Nessie\n" } sub new { bless {} } package Foo; sub lock { print "Foo lock\n" } my $trans = Lock::Ness-new; lock $trans; Run it. The result is "Foo lock". That's the way it should be, for the same reasons I've already pointed out. You don't want adding a method to a class to suddenly alter the behavior of distant code. But this doesn't really win you much besides some syntactic sugar. Consider this code: lock $trans{$var}; What if %trans is not tied? Then a lock() subroutine would have to be in scope However, here in the tie case I think it actually gains you a lot more than just sugar. Without this facility, you have to mix OO and tied calls snip No, I'm saying that if you're solely expecting %trans to always be tied and lock() to always be called as a method (which you have to, else you'd have to have a lock() method and a lock() function as I pointed out), then you may as well just have designed your interface as straight OO in the first place. Tying just buys you some cute syntax in this case. arguments for the RFC sniped This is the problem that the RFC is attempting to solve. So in this case, the indirect object syntax actually buys a lot. Yes, it does help solve those problems. The dangling untie() will happen less frequently, and you can customize the hell out of your tied class. But you're trading those problems for a new set of ambiguities! PS Your reply to Fowler hasn't hit the archives yet, so I'll hold off on jumping on his points until then. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse GuRuThuG make a channel called Perl, and infest it with joking and funit doesnt make alot of sense.
Re: RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
On Mon, Sep 11, 2000 at 01:31:39PM +1100, Damian Conway wrote: Or, better still, pass a reference to the actual variable being tied. Good idea. Also notice that I suggested the TIE be called as a method, so that it can be inherited if necessary (maybe you had that idea already???) The tie *can* currently be inherited. package Tie; sub TIESCALAR { print "Tie::TIESCALAR\n" } package Foo; @ISA = qw(Tie); package Bar; tie $thingy, "Foo"' Calls Tie::TIESCALAR, as expected. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse My room-mate has root I must now be filled with paste Summers here are hard. -- ignatz
Re: RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
On Sun, Sep 10, 2000 at 09:22:39PM -0700, Nathan Wiger wrote: Regardless of my huge error above, this doesn't change the fact that this is exactly what tie() does currently in Perl 5. That is: tie @a, 'Matrix'; push @a, $stuff; Now changes the meaning of push() in the current package. So the only real difference in this situation from a user standpoint is that "PUSH" becomes "push" per the RFC, plus they can now do this with any function they please. Things like push(), exists(), etc... all have well defined meanings. If you add a push() method to your tied class its going to be for putting stuff onto the end of a list. Methods which override built-in functions are obvious enough. However, anything which is *not* a built-in, may only share its name and nothing else. use Some::Module qw(do_something); tie @a, 'Matrix; do_something @a; Harmless enough. But what happens if do_something() looks like this: sub do_something { my @a = @_; add @a, qw(some stuff); } If Matrix has an add() method, then it will interfere with Some::Module::add() and cause do_something() to do something really, really different than what was expected. The problem is that Matrix::add() and Some::Module::add() are related by name *only* and are not interchangable. The danger is of methods unintentionally being called in place of unrelated functions. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse MORONS!
Re: RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
determine at compile time if $foo will be tied or not. Here's another: sub foo { my $hash = shift; print $hash-{foo}; } my %hash; tie Some::Class %hash; foo(\%hash); foo({foo = "bar"}); Obviously the code of foo() can't be translated. However, this problem is eerily similar to that of pseudohashes. You could make a way of declaring a lexical variable as being tied to a given class at compile time, similar to the my Dog $spot syntax ick. Again, I think the issue of translation is a red herring. I believe the problem to lie elsewhere. Ask on p5p and try compiling perl5 with gprof to see where the problem is. -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse MORONS!
Re: RFC 193 (v1) Objects : Core support for method delegation
On Mon, Sep 04, 2000 at 09:53:39PM -, Perl6 RFC Librarian wrote: Objects : Core support for method delegation I like it! One gripe (of course)... The proposed delegation mechanism would work via a pragma: use delegation attr1 = [qw( method1 method2 method3 )], attr2 = [qw( method4 method5 )], attr3 = [], attr4 = [], I will often use a more complicated data structure for my objects, often organizing all sub-objects into a hash of hashes... $obj-{locks}{MacOSX} = $macosx_obj; $obj-{locks}{Mac}= $mac_obj; $obj-{locks}{BSD}= $bsd_obj; which is nice when you stuff alot of things into an object. If I wanted to deligate to those objects in $obj-{locks}, how would I under your proposal? In a similar vein, I can see a use for wanting to deligate a set of methods to an entire list of objects. Consider... $obj-{locks} = [$macosx_obj, $mac_obj, $bsd_obj]; it would be nice to be able to state that "method1" should deligate to each object in the $obj-{locks} list until it is found. Also, what happens when a deligated attribute does not contain an object when Perl checks? Should it produce a warning? I'd say no. I can easily see cases where you'd like to be able to deligate to objects which may or may not be instanciated at run-time. If a warning was issued, it would be difficult to circumvent. You'd have to place a dummy object in that slot. PS You mentioned Class::Classless. Does any other language or system implement deligations? -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse Long, long time ago, in a far away galaxy, cells were formed. Cells are building blocks of different chemicals. --Alex Chiu, Immortality Guy
Re: RFC 189 (v1) Objects : Hierarchical calls to initializers and destructors
On Sat, Sep 02, 2000 at 03:18:06PM -0400, Mike Lambert wrote: In certain cases, like the one in which you proposed, you'd want to explicitly bypass the parent DESTROY. sub DESTROY { my $self = shift; $self-UNIVERSAL::DESTROY(@_); } would skip the automatic chaining because the function contains an explicit call to a superclass's DESTROY. As you said, sounds difficult to implement and difficult to document. Too much magic. In cases of more complex class hierarchies, you can explicitly call one parent class's DESTROY, and skip anothers. Bad, bad, bad. Busts encapsulation, poking around in your parent's hierarchy. Just to make it clear, I agree, in principle, with chaining DESTROY and SETUP. I'd just like to see all the caveats cleared away first. We already have a system that kinda works, there's no point in replacing it with another that only kinda works. Also, its not entirely clear why method chaining is desired only for constructor and destructors. What about every other method? -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse BOFH excuse #177: sticktion
Re: RFC 190 (v1) Objects : NEXT pseudoclass for method redispatch
On Fri, Sep 01, 2000 at 08:59:10PM -, Perl6 RFC Librarian wrote: This RFC proposes a new pseudoclass named CNEXT. This pseudoclass would provide a way of correctly redispatching a method or an autoloaded method. Yay! I have nothing constructive to say. (Yay!) -- Michael G Schwern http://www.pobox.com/~schwern/ [EMAIL PROTECTED] Just Another Stupid Consultant Perl6 Kwalitee Ashuranse But why? It's such a well designed cesspool of C++ code. Why wouldn't you want to hack mozilla? -- Ziggy