Re: Must exist, right?

2008-06-20 Thread David Nicol
this presumes a hash-based object instead of a field of a hash-based
object, but it can have blessed members unlike Chris Dolan's draft; it
also takes multiple args to be slice keys rather than consecutive
accesses into a deep AoA.  Wrapping in an import function and the
niftiness with closing over $fieldname has been left out,

UNTESTED.



package autoaccessor::ReadOnly;

sub new {
   shift; # lose package name
   bless shift #return what we were given, it had better be a hashref
}

sub AUTOLOAD{
   our $AUTOLOAD;
   $AUTOLOAD =~ /::DESTROY$/ and return;
   my ($fn) = $AUTOLOAD =~ m/([^:]+)\z/;
   my $obj = shift;
# closed-over fieldname trick goes here
   my @args = @_;
# without args, presume hash lookup of $fn
   @args or return $obj-{$fn};
# try access styles to see what works
   my @retval;
if (wantarray){
   eval [EMAIL PROTECTED] = @{$obj-[EMAIL PROTECTED];1} and return @retval;
   eval [EMAIL PROTECTED] = @{$obj-[EMAIL PROTECTED];1} and return @retval;
}else{
   eval [EMAIL PROTECTED] = @{$obj-[EMAIL PROTECTED];1} and return 
$retval[0];
   eval [EMAIL PROTECTED] = @{$obj-[EMAIL PROTECTED];1} and return 
$retval[0];
}
   Carp::croak( Cannot figure out how to access $fn member of $obj)
}

1;
__END__

=pod

Andy A's initial example would become

   package main;

   my $my_foo = new autoaccessor::ReadOnly {
   foo = [ 1, 2, 3 ],
   bar = { eat = 'drink', sleep = 'wake' },
   };

   my $two = $my_foo-foo( 1 );
   my $drink = $my_foo-bar-eat;

=cut


Re: Must exist, right?

2008-06-19 Thread Andy Armstrong

On 19 Jun 2008, at 03:18, Chris Dolan wrote:
Implemented!  See the attached .pm file and the test.pl file that  
verifies the four snipped use cases.  It could certainly be made  
more readable, but my interest is waning quickly.  :-)  I hereby  
grant anyone permission to use/extend this crappy code under the  
same license terms as Perl itself.



Heh. I can see this going all FizzBuzz :)

--
Andy Armstrong, Hexten






RE: Must exist, right?

2008-06-19 Thread Burak Gursoy
I think Moose is overkill for this type of thing but Andy++ for this thread,
I've been looking for something like this for a while too :)

-Original Message-
From: Andy Armstrong [mailto:[EMAIL PROTECTED] 
Sent: Thursday, June 19, 2008 3:23 AM
To: Eric Wilhelm
Cc: module-authors@perl.org
Subject: Re: Must exist, right?

On 19 Jun 2008, at 01:14, Eric Wilhelm wrote:
 You want something like Object::Accessor, but without needing to
 actually create the object?

Yup. I want a read-only object with dynamically generated per object  
methods that reflect the internal data structure.

 Assuming you could be bothered to call new() for the sub-object  
 (passing
 it to the contructor, etc), just about anything including Moose would
 work ;-)  I'll let the more Moose-enabled folks comment on how
 a 'default' sub (or some other setup) would do exactly what you want.


I really /must/ look at Moose properly soon :)

-- 
Andy Armstrong, Hexten





Re: Must exist, right?

2008-06-19 Thread Aristotle Pagaltzis
* Eric Wilhelm [EMAIL PROTECTED] [2008-06-19 10:15]:
 But even with C::A::Classy, I've had troubles with perception.
 I just got a project (which I originally architected) set in
 front of me for the second time after the client's in-house guy
 decided that he didn't understand C::A::Classy and opted to
 tear it out and replace it with a beta in-house thing that
 doesn't really even try to have most of the features of an
 object system - thereby loosing the read-only distinctions,
 private mutators, immutable properties on some attributes, etc
 - and switching all of the calling conventions to require
 sprinkling extra curlies. The net difference in the code comes
 from a lot of little details, but I could point to completely
 redundant classes which exist solely because the lack of object
 system led to their creation. I think that might be overkill.

This is the same reason people write their own crappy templating
systems. “I just need to do this one little thing and that whole
template engine looks so intimidating, I’ll just write a few
lines of code to do this myself.” Of course they end up expending
extra effort to deal with the absence of various conveniences of
a full-featured system, and the five-line solution inevitably
grows until it has 1/3rd the features of a full-featured system
except that the in-house solution is an organically grown mudball
rather than a coherently designed whole.

It’s OK, mind, to write your own templating system. Or meta
object library. Or web framework. Or whatever. Just be sure you
want to. Especially if your goal is to put it into production,
you need be aware of the scope of the problem ahead of time; if
you resolve to do a thorough job and understand what you are
committing to, go ahead. OTOH if you want to experiment and you
don’t have any plans to inflict your creation on production code
then that’s great too: learning by doing provides the deepest
understanding.

But “$system/$library/$framework intimidates me” is not a valid
reason to do a zero-effort hack.

Regards,
-- 
Aristotle Pagaltzis // http://plasmasturm.org/


Must exist, right?

2008-06-18 Thread Andy Armstrong

I assume there's a module that works like this?

package MyFoo;

use Data::Auto::Objectify::Thing qw( my_data_field );

sub new {
bless {
my_data_field = {
foo = [ 1, 2, 3 ],
bar = { eat = 'drink', sleep = 'wake' },
}
  },
  shift;
}

package main;

my $my_foo = MyFoo-new;

my $two = $my_foo-foo( 1 );
my $eat = $my_foo-bar-eat;

In other words I want it to synthesise accessors based on the contents  
of a complex data structure. For bonus points it might also allow


# Can use subscript notation for hashes
my $eat = $my_foo-bar('eat');

And maybe allow multiple subscripts so that, for example, if I had a  
field called 'grid' that contained a rectangular array I could then do


my $point = $my_bar-grid(3, 5);

It's got to exist, right? I had a look but there are so many  
^(?:Object|Data)::.* modules that it's a bit hard to see the wood for  
the trees :)


--
Andy Armstrong, Hexten



Re: Must exist, right?

2008-06-18 Thread Andy Armstrong

On 19 Jun 2008, at 00:35, Andy Armstrong wrote:
It's got to exist, right? I had a look but there are so many  
^(?:Object|Data)::.* modules that it's a bit hard to see the wood  
for the trees :)



Ah. I see:

 http://search.cpan.org/dist/Class-AutoAccess/

But that creates accessor/mutators. I want to generate read only  
accessors and have any arguments to them interpreted as a path into  
the data structure below the point referred to by the accessor.


--
Andy Armstrong, Hexten






Re: Must exist, right?

2008-06-18 Thread Eric Wilhelm
# from Andy Armstrong
# on Wednesday 18 June 2008 16:35:

use Data::Auto::Objectify::Thing qw( my_data_field );

     sub new {
         bless {
             my_data_field = {
                 foo = [ 1, 2, 3 ],
                 bar = { eat = 'drink', sleep = 'wake' },
...

     my $two = $my_foo-foo( 1 );
     my $eat = $my_foo-bar-eat;

You want something like Object::Accessor, but without needing to 
actually create the object?

Assuming you could be bothered to call new() for the sub-object (passing 
it to the contructor, etc), just about anything including Moose would 
work ;-)  I'll let the more Moose-enabled folks comment on how 
a 'default' sub (or some other setup) would do exactly what you want.

--Eric
-- 
It ain't those parts of the Bible that I can't understand that
bother me, it's the parts that I do understand.
--Mark Twain
---
http://scratchcomputing.com
---


Re: Must exist, right?

2008-06-18 Thread David Nicol
Considering that Data::Dumper is entirely regular in how it will
present a deconstruction of the data structure, and you have a clear
concept of how you wish the example structure === accessor set thing
to work, it's certainly possible, and would take maybe two hacking
sessions to get right (provided you don't get swept into the lake by a
mini-tsunami.)

It seems like something that might not exist already, as the need to
share that kind of meta-abstraction is felt by only extreme show-offs
(such as various people on this list)

To make your example DWITYM, Data::Auto::Objectify::Thing would presume that
the structure returned by its caller has a Cnew that will return a
fully populated example object when called with no arguments, and
would postpone defining the accessors until the INIT phase, because
the {caller()::'new'} does not exist yet at Cimport time.

I would have Data::Auto::Objectify::Thing take an optional C example
= ...  import arg in addition to the wait-until-INIT trick, and
would bless the substructures into constructed-named packages under
Data::Auto::Objectify::Thing::Packages::... for example.

Tipjar::fields creates accessors for named fields by imposing array
object semantics on its calling package; recently I prefer to use
:lvalue subroutines for accessors rather than defining both get* and
put* s.

In your example, you are planning on subclassing MyFoo into a whole
family of kinds of hash-based objects that share this accessor set, or
something.  It's not clear if the elements are supposed to be
extensible or not.  If they aren't extensible, and there is a fixed
set of them, using an array-based object and naming all the slots with
lvalue accessors is the way I would do it

sub new { bless [], shift };
BEGIN{
   my $counter = -1;
   eval join '' map {$counter++; ACCESSOR} (qw/one two three eat sleep/)
   sub $_ : lvalue { shift()-[$counter] }
ACCESSOR
};

but of course I don't know exactly what you are trying to do.


Re: Must exist, right?

2008-06-18 Thread Andy Armstrong

On 19 Jun 2008, at 01:14, Eric Wilhelm wrote:

You want something like Object::Accessor, but without needing to
actually create the object?


Yup. I want a read-only object with dynamically generated per object  
methods that reflect the internal data structure.


Assuming you could be bothered to call new() for the sub-object  
(passing

it to the contructor, etc), just about anything including Moose would
work ;-)  I'll let the more Moose-enabled folks comment on how
a 'default' sub (or some other setup) would do exactly what you want.



I really /must/ look at Moose properly soon :)

--
Andy Armstrong, Hexten






Re: Must exist, right?

2008-06-18 Thread Andy Armstrong

On 19 Jun 2008, at 01:18, David Nicol wrote:

Considering that Data::Dumper is entirely regular in how it will
present a deconstruction of the data structure, and you have a clear
concept of how you wish the example structure === accessor set thing
to work, it's certainly possible, and would take maybe two hacking
sessions to get right (provided you don't get swept into the lake by a
mini-tsunami.)


Yeah, I've been sort of passively thinking about how to do it for a  
little while. I don't think it's too hard but I don't want to reinvent  
the wheel.



It seems like something that might not exist already, as the need to
share that kind of meta-abstraction is felt by only extreme show-offs
(such as various people on this list)


:)

To make your example DWITYM, Data::Auto::Objectify::Thing would  
presume that

the structure returned by its caller has a Cnew that will return a
fully populated example object when called with no arguments, and
would postpone defining the accessors until the INIT phase, because
the {caller()::'new'} does not exist yet at Cimport time.


I was thinking the accessors would be completely dynamic - AUTOLOADed.  
So creation of the data structure can happen at any time before you  
start calling accessors.



I would have Data::Auto::Objectify::Thing take an optional C example
= ...  import arg in addition to the wait-until-INIT trick, and
would bless the substructures into constructed-named packages under
Data::Auto::Objectify::Thing::Packages::... for example.


I wasn't thinking of making dynamic packages at all. See above.


Tipjar::fields creates accessors for named fields by imposing array
object semantics on its calling package; recently I prefer to use
:lvalue subroutines for accessors rather than defining both get* and
put* s.

In your example, you are planning on subclassing MyFoo into a whole
family of kinds of hash-based objects that share this accessor set, or
something.  It's not clear if the elements are supposed to be
extensible or not.  If they aren't extensible, and there is a fixed
set of them, using an array-based object and naming all the slots with
lvalue accessors is the way I would do it



I basically want to be able to create read only 'value' objects that  
wrap a data structure that's created dynamically at runtime. A  
concrete example: I've just written some code that parses a formatted  
summary of memory usage for a server product. There are five named  
metrics for each of around 30 named categories of memory usage. My  
code just parses what it finds - it doesn't know any of the names  
ahead of time and the names might change as the product evolves.


I'd like the object that falls out of the end to let me do e.g.:

 print $mem-relay_buffer-allocations;

instead of

 print $mem-get('relay_buffer', 'allocations');

which is how it looks at the moment.

--
Andy Armstrong, Hexten






Re: Must exist, right?

2008-06-18 Thread Chris Dolan

On Jun 18, 2008, at 6:35 PM, Andy Armstrong wrote:


I assume there's a module that works like this?


[snip]

It's got to exist, right? I had a look but there are so many ^ 
(?:Object|Data)::.* modules that it's a bit hard to see the wood  
for the trees :)


--
Andy Armstrong, Hexten



Implemented!  See the attached .pm file and the test.pl file that  
verifies the four snipped use cases.  It could certainly be made more  
readable, but my interest is waning quickly.  :-)  I hereby grant  
anyone permission to use/extend this crappy code under the same  
license terms as Perl itself.


Chris


package MyFoo;

use Data::Auto::Objectify::Thing qw( my_data_field );

sub new {
   bless {
  my_data_field = {
 foo = [ 1, 2, 3 ],
 bar = { eat = 'drink', sleep = 'wake' },
 grid = [
[1,2,3,4,5,6], [7,8,9,10,11,12],
[13,14,15,16,17,18], [19,20,21,22,23,24],
 ],
  }
   },
   shift;
}

package main;
use Test::More tests = 4;

my $my_foo = MyFoo-new;

is($my_foo-foo( 1 ), 2);
is($my_foo-bar-eat, 'drink');
is($my_foo-bar('eat'), 'drink');
is($my_foo-grid(3, 5), 24);


package Data::Auto::Objectify::Thing;
use warnings;
use strict;
use Carp;
use Data::Dumper;

sub import {
   my ($pkg, $fieldname) = @_;
   my $caller_pkg = caller(0);
   no strict 'refs';
   *{$caller_pkg . '::AUTOLOAD'} = sub {
  my ($self, @args) = @_;
  my $autoload = do {
 no strict 'vars';
 $AUTOLOAD;
  };
  return if $autoload =~ /::DESTROY$/;
  my ($fn) = $autoload =~ m/([^:]+)\z/xms;
  if (defined $fieldname) {
 $self = $self-{$fieldname};
  }
  if (!exists $self-{$fn}) {
 croak 'No such field ' . $fn;
  }
  my $field = $self-{$fn};
  if (!ref $field) {
 return $field;
  }
  if ('ARRAY' eq ref $field) {
 $field = $field-[$_] for @args;
 return $field;
  }
  my $obj = bless {xyzzy = $field}, 'Data::Auto::Objectify::Thing::anon';
  $obj = $obj-$_() for @args;
  return $obj;
   };
   return;
}

package Data::Auto::Objectify::Thing::anon;
Data::Auto::Objectify::Thing-import('xyzzy');
1;