Re: Custom object constructors

2009-08-27 Thread Moritz Lenz
Kevan Benson wrote:
 That said, I submit that it's a very confusing part of the language as 
 defined currently, and I haven't seen a very thorough explanation of the 
 purpose of each method in the chain the instantiates a new object.  S12 
 touches upon them slightly, but not in enough detail that I was able to 
 work out where I should be adding code to appropriately make alternate 
 constructors.

I've tried to explain that here:

http://perlgeek.de/blog-en/perl-6/object-construction-and-initialization.html

(If anybody thinks part of this is worthy backporting to the specs, feel
free).

Cheers,
Moritz


Re: Custom object constructors

2009-08-20 Thread Moritz Lenz
Kevan Benson wrote:
 Should there not be a way to define object constructors with custom 
 signatures that can be usefully invoked like a normal constructor?
 
 Currently, defining a BUILD method for a class with a specific signature 
 doesn't seem to allow for the object to be invoked by new with that 
 signature and be correctly passed to the right BUILD method.  It seems a 
 whole chain of new - bless - BUILDALL - BUILD would need to be 
 defined with specific signatures just to get a custom constructor.

No. It's enough to write a method .new that calls bless, which in turn
calls BUILDALL (which re-dispatches to BUILD) (sorry if I got the order
wrong in that IRC conversation).


Let's assume we define default new() method with signature (*...@p, *%n)
that passes positional arguments to BUILD as BUILD(|@p, |%n), then we
might not be able to call BUILD submethods from superclasses (because
they don't expect any positional parameters), so you basically loose
compatibility with any super classes by introducing positional
parameters. Not a good idea.

It seems much more sane as it is now, that is to modify only the
signature of new new() methods, not of BUILD methods.

Cheers,
Moritz


Re: Custom object constructors

2009-08-20 Thread Kevan Benson

Moritz Lenz wrote:

Kevan Benson wrote:
Should there not be a way to define object constructors with custom 
signatures that can be usefully invoked like a normal constructor?


Currently, defining a BUILD method for a class with a specific signature 
doesn't seem to allow for the object to be invoked by new with that 
signature and be correctly passed to the right BUILD method.  It seems a 
whole chain of new - bless - BUILDALL - BUILD would need to be 
defined with specific signatures just to get a custom constructor.


No. It's enough to write a method .new that calls bless, which in turn
calls BUILDALL (which re-dispatches to BUILD) (sorry if I got the order
wrong in that IRC conversation).


Let's assume we define default new() method with signature (*...@p, *%n)
that passes positional arguments to BUILD as BUILD(|@p, |%n), then we
might not be able to call BUILD submethods from superclasses (because
they don't expect any positional parameters), so you basically loose
compatibility with any super classes by introducing positional
parameters. Not a good idea.

It seems much more sane as it is now, that is to modify only the
signature of new new() methods, not of BUILD methods.


Okay, I can accept that.  Most of my objections seemed to stem from 
misunderstanding what can be done in .new (or stated more succinctly, 
what can be done *easily* in .new).  I was under the impression that 
since it was before bless, operations like calling methods on the object 
might be harder to do, but it's nothing that can't be worked around.


That said, I submit that it's a very confusing part of the language as 
defined currently, and I haven't seen a very thorough explanation of the 
purpose of each method in the chain the instantiates a new object.  S12 
touches upon them slightly, but not in enough detail that I was able to 
work out where I should be adding code to appropriately make alternate 
constructors.


--

-Kevan Benson
-A-1 Networks


Re: Custom object constructors

2009-08-20 Thread Jan Ingvoldstad
On Thu, Aug 20, 2009 at 10:44 PM, Kevan Benson kben...@a-1networks.comwrote:


 That said, I submit that it's a very confusing part of the language as
 defined currently, and I haven't seen a very thorough explanation of the
 purpose of each method in the chain the instantiates a new object.  S12
 touches upon them slightly, but not in enough detail that I was able to work
 out where I should be adding code to appropriately make alternate
 constructors.


Now that you apparently understand it, do you have a suggestion on how S12
might be phrased differently?

I must admit that I don't quite grasp the concepts here yet, so an alternate
wording might help others as well.

Thanks for bringing the question up.
-- 
Jan


Re: Custom object constructors

2009-08-20 Thread Kevan Benson

Jan Ingvoldstad wrote:

On Thu, Aug 20, 2009 at 10:44 PM, Kevan Benson kben...@a-1networks.comwrote:


That said, I submit that it's a very confusing part of the language as
defined currently, and I haven't seen a very thorough explanation of the
purpose of each method in the chain the instantiates a new object.  S12
touches upon them slightly, but not in enough detail that I was able to work
out where I should be adding code to appropriately make alternate
constructors.



Now that you apparently understand it, do you have a suggestion on how S12
might be phrased differently?

I must admit that I don't quite grasp the concepts here yet, so an alternate
wording might help others as well.

Thanks for bringing the question up.


Unfortunately I'm not at all confident I do understand it all, but I'll 
explain how I think it works and people more knowledgeable than me will 
hopefully step in and explain where I'm wrong.  Maybe out of this we can 
get some consensus on what needs to be added WRT object constructors in S12.


The creation sequence looks something like this:
.new(args) {
my $self = .bless(class,  {
.BUILDALL(class, args) {
# in reverse MRO
for (@parent) { .BUILD(class, args) }
.BUILD(class, args)
}
}

Note: Actually, I believe the current .BUILD is actually called as part 
of the call to all parent .BUILD methods in Rakudo.  At least that's 
what I'm able to infer from the parrot code for Rakudo objects at 
src/classes/Object.pir starting at line 272 (thanks japhb!).


.new - Handles the actual call to .new from code, define other 
submethods/methods for this if you want to create alternate 
constructors.  You should normalize all paramaters to named values 
before calling .bless.  S12 implies that any .new you write (or a 
constructor of any other name you define) must call .bless.


.bless - See S12 
(http://perlcabal.org/syn/S12.html#Construction_and_Initialization) for 
more info, but this is responsible for actually creating the object 
(unless .CREATE called before and opaque object passed) and calling the 
BUILD routines.


.BUILDALL - If it's still valid, http://dev.perl.org/perl6/rfc/189.html 
seems to cover the expected behavior of this.


.BUILD - Used for object initialization, assigning passed named values 
(pairs) to object attributes if they match, or doing something more 
complex to initialize the object correctly based on supplied data.



Some things to be wary of or that I'm still hazy on:

What sort of calling syntax can be used in .new since the object isn't 
yet blessed?  Or since .new encapsulates .bless (right?), I guess you 
can call normally AFTER the bless.


.new happens before calling parent constructors, .BUILD happens after, 
so .new possibly won't have access to some default attributes as defined 
by parent classes/roles.


Theoretically you could define a custom constructor, normalize data, 
call the regular .new constructor, and post process on the object 
returned before returning it yourself, I think.


--

-Kevan Benson
-A-1 Networks


Re: Custom object constructors

2009-08-19 Thread Kevan Benson


I think the too much magic is in automatically creating the 
appropriate new method with that signature.  I idea is to get the 
standard behavior, which is to define a method that's signature is used 
for the instantiation.


Currently, I believe you have to define at least new and BUILD, not just 
one or the other.  I guess you could redefine new and parse your 
arguments into the correct named pair arguments the other initialization 
functions (bless, BUILDALL, BUILD) expect, but that would be before 
blessing, and seems sort of limiting.


Mark J. Reed wrote:

I'm confused.  The signature of initialize is used by Class.new in
Ruby; the signature of __init__ is used by class_name() in Python...
How is doing the same thing too much magic?  Or am I misunderstanding
the suggestion?

On 8/19/09, Kevan Benson kben...@a-1networks.com wrote:

Should there not be a way to define object constructors with custom
signatures that can be usefully invoked like a normal constructor?

Currently, defining a BUILD method for a class with a specific signature
doesn't seem to allow for the object to be invoked by new with that
signature and be correctly passed to the right BUILD method.  It seems a
whole chain of new - bless - BUILDALL - BUILD would need to be
defined with specific signatures just to get a custom constructor.

Two possible thoughts on how to achieve this were put forth in the
#perl6 discussion.  One, auto build the chain on definition of a BUILD
method, which was thought be some to be a bit too magical (me included,
even though it was my suggestion at first).  Alternatively, pass the
capture of arguments as supplied by new down the chain of initialization
methods so any that were defined as multi's can be called correctly by
multiple dispatch at the correct point.

I'm aware there's a default constructor that allows named parameters to
be set, but I think the usefulness of allowing specific constructors
that take defined parameters and initialize the object as needed should
not be overlooked.  E.g.
 my DateModule $d .= new('2007-03-12');



Relevant bits of #perl6 discussion copied below:

(2009-08-19 11:47:49) Kentrak: Q re: object initialization in p6; Should
defining a BUILD with a non standard signature imply an implicit
declaration of new with the same signature?
(2009-08-19 11:48:05) moritz_: KyleHa: no
(2009-08-19 11:48:23) moritz_: erm sorry, meant Kentrak
(2009-08-19 11:48:26) moritz_: tab fail :/
(2009-08-19 11:48:35) moritz_: Kentrak: it's a nice idea, but it seems
like too much magic to me
(2009-08-19 11:48:50) Kentrak: moritz_: I'm aware it doesn't currently,
but it seems like it really makes sense
(2009-08-19 11:48:59) Kentrak: moritz_: in a DWIMmy sort of way
(2009-08-19 11:49:28) moritz_: Kentrak: right, but I don't see how it
fits in the current system without defining a huge exception
(2009-08-19 11:49:29) r0bby left the room (quit: Read error: 104
(Connection reset by peer)).
(2009-08-19 11:49:34) r0bby [n=wakaw...@guifications/user/r0bby] entered
the room.
(2009-08-19 11:49:43) __ash__: jnthn: http://gist.github.com/170571
(2009-08-19 11:49:51) Kentrak: moritz_: it seems I need to define a
new() AND a BUILD() with matching signatures just to get the
initialization syntax I want, soI might as well use new(), but then I
have to cless...
(2009-08-19 11:49:52) moritz_: anyway, I'll think about it
(2009-08-19 11:50:02) Kentrak: err, bless
(2009-08-19 11:50:15) moritz_: Kentrak: no, new() is enough, no need for
another BUILD
mofino molaf moritz_
mofino molaf moritz_
(2009-08-19 11:50:52) moritz_: well, maybe we could have a new() with
slurpy positional arguments
(2009-08-19 11:50:55) masak: I override new() when I want magic
parameter handling, and BUILD when I want non-standard object
initialization.
(2009-08-19 11:50:56) japhb: moritz_, What are your rules of thumb for
when to use the various ways (implicit and explicit) to define constructors?
(2009-08-19 11:51:13) masak: #p6s in 10, by the way.
(2009-08-19 11:51:28) dalek: rakudo: 5a85869 | pmichaud++ |
docs/announce/2009-08:
(2009-08-19 11:51:28) dalek: rakudo: Small fix to release announcement.
(2009-08-19 11:51:28) dalek: rakudo: review:
http://github.com/rakudo/rakudo/commit/5a85869ddbc17095cdb884f10a6cd1618804d773
(2009-08-19 11:51:31) moritz_: and have it try to dispatch to a BUILD
method, and fail if there's no matching one
(2009-08-19 11:51:37) jnthn: __ash__: OK, looks sane.
(2009-08-19 11:51:41) jnthn: __ash__: Two questions
(2009-08-19 11:51:42) Kentrak: moritz_:  so if I want to add initializer
methods to support something like my DateModule $d .= new('2007-03-12');
then I have to define new() submethods and use bless like in p5?
(2009-08-19 11:51:47) jnthn: 1) Does it make what you wanted to work
actually work?
(2009-08-19 11:51:51) moritz_: japhb: sorry, I'm involved in too many
things at a time, maybe I'll blog later about it
(2009-08-19 11:51:55) jnthn: 2) Does it still pass the spectests? :-)
(2009-08-19 11:51:58) 

Re: Custom object constructors

2009-08-19 Thread Daniel Ruoso
Em Qua, 2009-08-19 às 15:37 -0700, Kevan Benson escreveu:
 Should there not be a way to define object constructors with custom 
 signatures that can be usefully invoked like a normal constructor?

What's the problem with

method new(Str $timestamp) {
   self.SUPER::new(ts = strptime('...',$timestamp));
}

?

 Currently, defining a BUILD method for a class with a specific signature 
 doesn't seem to allow for the object to be invoked by new with that 
 signature and be correctly passed to the right BUILD method.  It seems a 
 whole chain of new - bless - BUILDALL - BUILD would need to be 
 defined with specific signatures just to get a custom constructor.

BUILD allows you to tweaken the initialization of known attributes. Your
BUILD submethod will only receive then named arguments for the
attributes locally defined in your class.

The purpose of BUILD is *not* to provide alternative signatures to the
constructor.

 Two possible thoughts on how to achieve this were put forth in the 
 #perl6 discussion.  One, auto build the chain on definition of a BUILD 
 method, which was thought be some to be a bit too magical (me included, 
 even though it was my suggestion at first).  Alternatively, pass the 
 capture of arguments as supplied by new down the chain of initialization 
 methods so any that were defined as multi's can be called correctly by 
 multiple dispatch at the correct point.

The bless-BUILDALL-BUILD chain uses the positional arguments as the
candidate protoobjects that define additional parameters for the
builders. the named parameters are passed to each BUILD method for
initialization.

Again, if you want a custom signature for new, just write a custom new.

daniel



Re: Custom object constructors

2009-08-19 Thread David Green

On 2009-Aug-19, at 4:37 pm, Kevan Benson wrote:
I'm aware there's a default constructor that allows named parameters  
to be set, but I think the usefulness of allowing specific  
constructors that take defined parameters and initialize the object  
as needed should not be overlooked.  E.g.

   my DateModule $d .= new('2007-03-12');


My first thought is also coercion: say my DateModule $d = '2007-03-12'  
and let DateModule::.(Str) worry about making the new object.


(Or does that need to be my DateModule $d = DateModule('2007-03-12')?   
That seems unnecessarily redundant.)



-David