Re: Stupid Newbie Question

2001-11-15 Thread Michael G Schwern

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

2001-11-08 Thread Michael G Schwern

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

2001-11-08 Thread Michael G Schwern

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

2000-12-16 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-18 Thread Michael G Schwern

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

2000-09-17 Thread Michael G Schwern

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

2000-09-17 Thread Michael G Schwern

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

2000-09-15 Thread Michael G Schwern

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

2000-09-14 Thread Michael G Schwern

=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

2000-09-14 Thread Michael G Schwern

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)

2000-09-10 Thread Michael G Schwern

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)

2000-09-10 Thread Michael G Schwern

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)

2000-09-10 Thread Michael G Schwern

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)

2000-09-10 Thread Michael G Schwern

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)

2000-09-07 Thread Michael G Schwern
 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

2000-09-04 Thread Michael G Schwern

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

2000-09-02 Thread Michael G Schwern

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

2000-09-01 Thread Michael G Schwern

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