Re: Custom object constructors

2009-08-26 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 Kevan Benson

Jan Ingvoldstad wrote:

On Thu, Aug 20, 2009 at 10:44 PM, 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.



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-20 Thread Jan Ingvoldstad
On Thu, Aug 20, 2009 at 10:44 PM, 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.


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

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 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-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



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 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  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) japhb: moritz_, no

Re: Custom object constructors

2009-08-19 Thread Mark J. Reed
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  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) japhb: moritz_, nod
> (2009-08-19 11:52:11) masak: Kentrak: basically, yes.
> (2009-08-19 11:52:12) moritz_: Kentrak: roughly, yes
> (2009-08-19 11:52:37) jnthn: Kentrak: You'll generally want new to be
> method, not submethod, though.
> (2009-08-19 11:52:39) Kentrak: moritz_: actually, I assumed new() calls
> BUILD(), does it?  If it does, can't we just pass the same sig to BUILD
> after blessing?
> (2009-08-19 11:52:43) masak: Kentr

Custom object constructors

2009-08-19 Thread Kevan Benson


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) japhb: moritz_, nod
(2009-08-19 11:52:11) masak: Kentrak: basically, yes.
(2009-08-19 11:52:12) moritz_: Kentrak: roughly, yes
(2009-08-19 11:52:37) jnthn: Kentrak: You'll generally want new to be 
method, not submethod, though.
(2009-08-19 11:52:39) Kentrak: moritz_: actually, I assumed new() calls 
BUILD(), does it?  If it does, can't we just pass the same sig to BUILD 
after blessing?
(2009-08-19 11:52:43) masak: Kentrak: .CREATE and .bless is how you 
create objects in Perl 6.
(2009-08-19 11:53:04) masak: Kentrak: I think .bless calls BUILDALL, 
which calls BUILD.

(2009-08-19 11:53:10) jnthn: .bless will trigger...yes, what masak said.
(2009-08-19 11:53:17) moritz_: pmichaud: funny, I had the exact same 
fixes, byte by byte ;-)
(2009-08-19 11:53:18) Kentrak: masak: Hmm, I'm finding the