still crabby about copy constuctor craziness

U

Unknown Poster

I'm not even able to verify that a "copy constructor" is called even when "="
is overloaded and code like that on page 357 of Programming Perl 3E runs:

$copy = $original;
$++copy;
----------------------
This is perl, v5.6.1 built for MSWin32-x86-multi-thread

in my class:

use overload "=" => \&c;


sub c
{
# there was other code here, but it makes no difference
print "in copy constructor \n";
}


I don't even know what a copy constructor ought to look like (an example
in P.P is needed), but I have a print statement to at least show that
the "c" sub is run. I run code using the class - there are no
errors, but the print statement never outputs anything. What's going on?
 
A

A. Sinan Unur

(e-mail address removed) (Unknown Poster) wrote in
I'm not even able to verify that a "copy constructor" is called even
when "=" is overloaded and code like that on page 357 of Programming
Perl 3E runs:

$copy = $original;
$++copy;
----------------------
This is perl, v5.6.1 built for MSWin32-x86-multi-thread

in my class:

use overload "=" => \&c;


sub c
{
# there was other code here, but it makes no difference
print "in copy constructor \n";
}


I don't even know what a copy constructor ought to look like (an
example in P.P is needed), but I have a print statement to at least
show that the "c" sub is run. I run code using the class - there are
no errors, but the print statement never outputs anything. What's
going on?

I am not sure. I had not overloaded anything in Perl until I read this
message and my curiosity led me to waste some time reading

perldoc overload

I came up with the following code. It is probably not a good idea to
infer too much about the right way of doing things from my code but it
seems work :) On the other hand, if you asked me why I overloaded the
increment and the stringfication operators also, my only answer is
because the code would not run without them.

I am hoping someone more knowledgable than myself will offer some
insights and corrections. Code follows:

use strict;
use warnings;

package Copyable;

sub new {
my ($class, $value) = @_;
bless \$value, $class;
}

sub value { ${$_[0]}; }

use overload '=' => 'copyctor';
use overload '++' => 'increment';
use overload '""' => 'tostring';

sub copyctor { my $copy = ${$_[0]}; bless \$copy; }

sub increment { ++${$_[0]}; shift; }

sub tostring { "${$_[0]}"; }

package main;

my $v = Copyable->new(10);

my $z = $v;
print ++$z;

__END__

C:\Home> copyctor.pl
11
 
A

Anno Siegel

Unknown Poster said:
I'm not even able to verify that a "copy constructor" is called even when "="
is overloaded and code like that on page 357 of Programming Perl 3E runs:

$copy = $original;
$++copy;
----------------------
This is perl, v5.6.1 built for MSWin32-x86-multi-thread

in my class:

use overload "=" => \&c;


sub c
{
# there was other code here, but it makes no difference
print "in copy constructor \n";
}


I don't even know what a copy constructor ought to look like (an example
in P.P is needed), but I have a print statement to at least show that
the "c" sub is run.

I suppose, the author(s) thought, "copy constructor", i.e. "constructor
of a copy", was self-explanatory. It is a method that returns a *copy*
of the given object (as opposed to a pointer to the same object).
I run code using the class - there are no
errors, but the print statement never outputs anything. What's going on?

Have you looked up "Copy Constructor" in "perldoc overload"? There it
says:

This operation is called in the situations when a mutator is applied to
a reference that shares its object with some other reference, such as

$a=$b;
++$a;

Whatever that means in detail, it says that overloading "=" is only
relevant in situations where you also overload a mutator, like "++".
Since you don't do that, the operation for "=" never had a chance of
being called.

If you don't intend to overload mutators, don't worry about it.
Understanding "=" is not essential to understanding overloading.
It is a workaround for a nasty side-effect of overloading mutators.

If you do intend to overload mutators, build another example that
includes an overloaded mutator, and watch the copy constructor being
called in the situation sketched in the doc.

Anno
 
J

J. Romano

I'm not even able to verify that a "copy constructor" is called even when "="
is overloaded and code like that on page 357 of Programming Perl 3E runs:

$copy = $original;
$++copy;

use overload "=" => \&c;

Dear Unknown Poster,

A few weeks ago (on June 26), I posted a write-up explaining this
exact issue. I too was confused about this, even after reading the
"Programming Perl" book and "perldoc overload".

I recommend you read it. The subject is "Regarding copy
constructors and mutators" and it was posted to the
comp.lang.perl.misc newsgroup. This link should take you there:

http://groups.google.com/[email protected]

This posting explains when the copy constructor gets called (and
why). I spent a lot of time writing this, so I would appreciate it if
people would at least try reading it when they experience "copy
constructor crazyness". (It even contains a sample program so you can
follow along and see exactly what's happening.)

-- Jean-Luc
 
B

Ben Morrow

Quoth (e-mail address removed) (Unknown Poster):
I'm not even able to verify that a "copy constructor" is called even when "="
is overloaded and code like that on page 357 of Programming Perl 3E runs:

$copy = $original;
$++copy;
----------------------
This is perl, v5.6.1 built for MSWin32-x86-multi-thread

in my class:

use overload "=" => \&c;

sub c
{
# there was other code here, but it makes no difference
print "in copy constructor \n";
}


I don't even know what a copy constructor ought to look like (an example
in P.P is needed),

Have you read perldoc overload? You should *always* read the relevant
perldocs as well as any books.

The following may help you understand:

#!/usr/bin/perl

{{

package CC;

use subs qw/clone incr/;

use overload '++' => \&incr, '=' => \&clone, '""' => \&str;

sub new {
my $c = shift;
warn 'NEW';
return bless \do {my $o = 0}, $c;
}

sub clone {
my $s = shift;
warn 'CLONE';
return bless \do {my $o = $$s}, ref $s;
}

sub incr {
my $s = shift;
warn 'INCR';
return ++$$s;
}

sub str {
my $s = shift;
return $$s;
}

}}

warn 'about to call NEW';
my $x = CC->new;
warn 'about to copy';
my $y = $x;
warn 'about to incr';
$x++;
warn 'done';

__END__

about to call NEW at cc line 31.
NEW at cc line 13.
about to copy at cc line 33.
about to incr at cc line 35.
CLONE at cc line 19.
INCR at cc line 25.
done: 1, 0 at cc line 37.

Ben
 
U

Unknown Poster

Perhaps the implementation of 5.6 on Windows is just messed up. The behavior
I see simply does not match what is in the Camel book. If the guy who wrote
Perl can't explain how it's supposed to work, who am I supposed to believe?

First, this sentence on page 357, is, to put it charitably, misleading:

"The handler for = is used in situations where a mutator (such as ++,
--, or any of the assigment operators) is applied to a reference that
shares its object with another reference."

It ought to be ""... where an explicitly overloaded mutator ..."

Anyway, this means that a user of a class doesn't
know if a copy constructor will be called unless he/she knows if
the mutator has been explicitly overloaded. Simply unacceptable.


Now, this is just wrong, at least in my environment - page 354:

"The ++$a operation can be autogenerated ... However, this does not
trigger the copying behavior that a real ++ operator would."

My ++ is autogenerated. If it did NOT cause copying then $a == $b
after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.

Likewise, again on page 357:
"$copy = $original; $copy = $copy + 1;
then no copying occurs ..."

Again, $copy is one more than $original, so copying certainly did occur.

Maybe this mess will be fixed in Perl 6. Otherwise, there's always Java -
no such thing as a copy constructor, and no operator overloading.
 
J

Jay Tilton

(e-mail address removed) (Unknown Poster) wrote:

: Perhaps the implementation of 5.6 on Windows is just messed up. The behavior
: I see simply does not match what is in the Camel book.

Share with us a _complete_ program that demonstrates this discontinuity
between specification and implentation.

: If the guy who wrote
: Perl can't explain how it's supposed to work, who am I supposed to believe?
:
: First, this sentence on page 357, is, to put it charitably, misleading:
:
: "The handler for = is used in situations where a mutator (such as ++,
: --, or any of the assigment operators) is applied to a reference that
: shares its object with another reference."
:
: It ought to be ""... where an explicitly overloaded mutator ..."

Go ahead and submit a documentation patch.

: Anyway, this means that a user of a class doesn't
: know if a copy constructor will be called unless he/she knows if
: the mutator has been explicitly overloaded. Simply unacceptable.

Defining appropriate behavior when instances of a class are mutated is the
job for the class's author, not for the user and not for you.

: Now, this is just wrong, at least in my environment - page 354:
:
: "The ++$a operation can be autogenerated ... However, this does not
: trigger the copying behavior that a real ++ operator would."
:
: My ++ is autogenerated. If it did NOT cause copying then $a == $b
: after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.

Because you have not shown the class and its operator overloaders, your
assumptions on what has been autogenerated, your test and your
interpretation of its results are meaningless.

: Likewise, again on page 357:
: "$copy = $original; $copy = $copy + 1;
: then no copying occurs ..."
:
: Again, $copy is one more than $original, so copying certainly did occur.

Again, because you have not shown the class, you've demonstrated nothing.
You certainly haven't shown that Perl's documentation is wrong.

: Maybe this mess will be fixed in Perl 6. Otherwise, there's always Java -
: no such thing as a copy constructor, and no operator overloading.

Or you could simply not use that feature in your Perl code.
 
U

Unknown Poster

: Anyway, this means that a user of a class doesn't
: know if a copy constructor will be called unless he/she knows if
: the mutator has been explicitly overloaded. Simply unacceptable.

Defining appropriate behavior when instances of a class are mutated is the
job for the class's author, not for the user and not for you.


You've got to be joking. This is a violation of abstraction atits most
basic. The whole point of OO is to separate interface from implementation,
and this situation is as blatant a mixing of the two as you can get.

Perhaps Wall, Christiansen, and Orant are all afraid of the number 13,
as evidenced by this chapter being written in such a sloppy manner.
Here's another gem from page 357:

"If the copy constructor is required during the execution of some
mutator, but a handler for = was not specified, it can be autogenerated
as a string copy provided the object is a plain scalar and not
something fancier."

I would REALLY love to see an example of a "plain scalar" that is an object.
Heck, I wouldn't even call a reference to an object a "plain scalar".
: Now, this is just wrong, at least in my environment - page 354:
:
: "The ++$a operation can be autogenerated ... However, this does not
: trigger the copying behavior that a real ++ operator would."
:
: My ++ is autogenerated. If it did NOT cause copying then $a == $b
: after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.

Because you have not shown the class and its operator overloaders, your
assumptions on what has been autogenerated, your test and your
interpretation of its results are meaningless.

It's not explicitly overloaded, "fallback" is not set, there is no
"nomethod" handler, and the code runs without raising an exception,
so unless the Tooth Fairy has overloaded "++", it must (according
to the rules) be autogenerated.
: Likewise, again on page 357:
: "$copy = $original; $copy = $copy + 1;
: then no copying occurs ..."
:
: Again, $copy is one more than $original, so copying certainly did occur.

Again, because you have not shown the class, you've demonstrated nothing.
You certainly haven't shown that Perl's documentation is wrong.

Oh, yes I have ... see above
: Maybe this mess will be fixed in Perl 6. Otherwise, there's always Java -
: no such thing as a copy constructor, and no operator overloading.

Or you could simply not use that feature in your Perl code.

Better yet, the Perl gurus could design an "object oriented Perl" that
actually follows the tenents of OOP.

BTW, don't you just love the way you can "overload" a non-existent operator,
and get no error, no exception, no warning?
 
A

Anno Siegel

Unknown Poster said:
(e-mail address removed) (Jay Tilton) wrote in message



You've got to be joking. This is a violation of abstraction atits most
basic. The whole point of OO is to separate interface from implementation,
and this situation is as blatant a mixing of the two as you can get.

Yup.

Perl's approach to (not only) OO is pragmatic and minimalistic. You get
the stuff necessary to implement OO, but little care has been taken to
enforce the tenets of OO, like separation of implementation and interface,
encapsulation, private methods and what have you. Mind you, you can
implement all that in Perl, as Damian Conway demonstrates in _Object
Oriented Perl_, but very little is enforced from the get-go. Even plain
inheritance must be supported by the class author, it doesn't come for
free.

You find that deplorable, you may even say that, then, Perl OO isn't
OO at all. You wouldn't be the first to say so, and you'd be in good
company. Abigail has said things to that effect and, afaik has not
published OO Perl code.

Others go ahead with what's there and implement quite impressive
software with Perl OO methods. It's your choice. If you want
Java, you know where to find it.
Perhaps Wall, Christiansen, and Orant are all afraid of the number 13,
as evidenced by this chapter being written in such a sloppy manner.
Here's another gem from page 357:

"If the copy constructor is required during the execution of some
mutator, but a handler for = was not specified, it can be autogenerated
as a string copy provided the object is a plain scalar and not
something fancier."

I would REALLY love to see an example of a "plain scalar" that is an object.
Heck, I wouldn't even call a reference to an object a "plain scalar".

Nor should you.

Perl parlance with respect to references is traditionally sloppy. We
often speak of "arrays" and "hashes" where "array reference" and "hash
reference" would be correct. Even more so, we say "object" when what
we really have is an "object reference". That is because we *must*
access an object through a reference. The object itself, the under-
lying (blessed) data structure is rather useless (and taboo, under
OO strictures).

So, in my view, saying that an object is a plain scalar is in fact
correct. Calling a ref to the scalar an "object" is common practice,
but sloppy.

Otherwise, I am quite with you that the documentation of Perl's overloading
could be better written. I have struggled with it myself.

The documentation is as open as the source. Until someone sits down
and re-writes the overload chapter, we got to work with what we have.

[big snip]
Better yet, the Perl gurus could design an "object oriented Perl" that
actually follows the tenents of OOP.

Tenets. Perl 6 will most likely be that. The current implementation
deliberately is not. That gives us additional degrees of freedom, for
instance to use one aspect of OO but not others. The Exporter module
uses inheritance, but little more. I wouldn't call it a class.
BTW, don't you just love the way you can "overload" a non-existent operator,
and get no error, no exception, no warning?

Minor quibble. Report a bug if it bothers you. I'm sure it is trivial
to fix.

Anno
 
A

Anno Siegel

Unknown Poster said:
(e-mail address removed) (Jay Tilton) wrote in message



You've got to be joking. This is a violation of abstraction atits most
basic. The whole point of OO is to separate interface from implementation,
and this situation is as blatant a mixing of the two as you can get.

Yup.

Perl's approach to (not only) OO is pragmatic and minimalistic. You get
the stuff necessary to implement OO, but little care has been taken to
enforce the tenets of OO, like separation of implementation and interface,
encapsulation, private methods and what have you. Mind you, you can
implement all that in Perl, as Damian Conway demonstrates in _Object
Oriented Perl_, but very little is enforced from the get-go. Even plain
inheritance must be supported by the class author, it doesn't come for
free.

You may find that deplorable, you may even say that, then, Perl OO isn't
OO at all. You wouldn't be the first to say so, and you'd be in good
company. Abigail has said things to that effect and, afaik has not
published OO Perl code.

Others go ahead with what's there and implement quite impressive
software with Perl OO methods. It's your choice. If you want
Java, you know where to find it.
Perhaps Wall, Christiansen, and Orant are all afraid of the number 13,
as evidenced by this chapter being written in such a sloppy manner.
Here's another gem from page 357:

"If the copy constructor is required during the execution of some
mutator, but a handler for = was not specified, it can be autogenerated
as a string copy provided the object is a plain scalar and not
something fancier."

I would REALLY love to see an example of a "plain scalar" that is an object.
Heck, I wouldn't even call a reference to an object a "plain scalar".

Nor should you.

Perl parlance with respect to references is traditionally sloppy. We
often speak of "arrays" and "hashes" where "array reference" and "hash
reference" would be correct. Even more so, we say "object" when what
we really have is an "object reference". Because we *must* access an
object through a reference, the term "object reference" is rarely used.
The object itself, the underlying (blessed) data structure is rather
useless (and taboo, under OO strictures), so it doesn't hurt (much)
that there is no distinct term for it.

So, in my view, saying that an object is a plain scalar is in fact
correct. Calling a ref to the scalar an "object" is common practice,
but sloppy.

Otherwise, I am quite with you that the documentation of Perl's overloading
could be better written. I have struggled with it myself.

The documentation is as open as the source. Until someone sits down
and re-writes the overload chapter, we got to work with what we have.

[big snip]
Better yet, the Perl gurus could design an "object oriented Perl" that
actually follows the tenents of OOP.

Tenets. Perl 6 will most likely be that. The current implementation
deliberately is not. That gives us additional degrees of freedom, for
instance to use one aspect of OO but not others. The Exporter module
uses inheritance, but little more. I wouldn't call it a class.
BTW, don't you just love the way you can "overload" a non-existent operator,
and get no error, no exception, no warning?

Minor quibble. Report a bug if it bothers you. I'm sure it is trivial
to fix.

Anno
 
B

Ben Morrow

[you're very close to going in the killfile. I'd tone down your comments
*just* a little if I were you...]

Quoth (e-mail address removed) (Unknown Poster):
You've got to be joking. This is a violation of abstraction atits most
basic. The whole point of OO is to separate interface from implementation,
and this situation is as blatant a mixing of the two as you can get.

Please explain... AFAICS, the only person who needs to know if a copy
constructor is called or not is the class's author, and they are exactly
the only person who knows whether ++ was explicitly overloaded or not.
Am I missing something?
Perhaps Wall, Christiansen, and Orant are all afraid of the number 13,
as evidenced by this chapter being written in such a sloppy manner.

Rudeness will get you nowhere, fast.
Here's another gem from page 357:

"If the copy constructor is required during the execution of some
mutator, but a handler for = was not specified, it can be autogenerated
as a string copy provided the object is a plain scalar and not
something fancier."

I would REALLY love to see an example of a "plain scalar" that is an object.
Heck, I wouldn't even call a reference to an object a "plain scalar".

<*seriously* picky mode>
The object is the refer*ant*, not the reference. It is the referant
which is blessed, not the reference (even though the blessing is done
through a ref). Thus

sub new {
return bless \do { my $o = "hello world" }, shift;
}

is a constructor for an object which is a plain scalar: that is, it
creates a scalar, blesses it and returns a ref to it.

$a and $b are both refs, so to say '$a is one more than $b' is
meaningless.
It's not explicitly overloaded, "fallback" is not set, there is no
"nomethod" handler, and the code runs without raising an exception,
so unless the Tooth Fairy has overloaded "++", it must (according
to the rules) be autogenerated.

Can you post a complete working program that demonstrates, please?
Better yet, the Perl gurus could design an "object oriented Perl" that
actually follows the tenents of OOP.

....or you could simply learn how OO works in Perl?
BTW, don't you just love the way you can "overload" a non-existent operator,
and get no error, no exception, no warning?

This is a forward-compatibility feature. If new overloadable tags are
added later, old perls running new programs will simply ignore them.

Ben
 
J

Jay Tilton

(e-mail address removed) (Unknown Poster) wrote:

: (e-mail address removed) (Jay Tilton) wrote in message :
: > : Now, this is just wrong, at least in my environment - page 354:
: > :
: > : "The ++$a operation can be autogenerated ... However, this does not
: > : trigger the copying behavior that a real ++ operator would."
: > :
: > : My ++ is autogenerated. If it did NOT cause copying then $a == $b
: > : after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.
: >
: > Because you have not shown the class and its operator overloaders, your
: > assumptions on what has been autogenerated, your test and your
: > interpretation of its results are meaningless.
:
: It's not explicitly overloaded, "fallback" is not set, there is no
: "nomethod" handler, and the code runs without raising an exception,
: so unless the Tooth Fairy has overloaded "++", it must (according
: to the rules) be autogenerated.

That's nice, dear. Are you going to show the class or not?
 
J

J. Romano

Anyway, this means that a user of a class doesn't
know if a copy constructor will be called unless he/she knows if
the mutator has been explicitly overloaded. Simply unacceptable.

I don't think it's unacceptable. When the copy constructor gets
called is the business of the programmer who wrote the class. If the
class writer wrote the class well, then the user of the class doesn't
have to concern him/herself with when the copy constructor gets called
or if a mutator has been explicitly overloaded.

Consider the Math::BigInt package. Over the years, there have been
different implementations of this class. Old versions of Math::BigInt
would autogenerate certain mutators (like "++" and "--"), but the
newest version explicitly overloads them (for efficiency's sake).
Calls to Math::BigInt's copy constructor will happen in one version
where it will not happen in the other. Yet the output is the same,
meaning that a programmer that uses Math::BigInt does not need to know
about Math::BigInt's internals like when the copy constructor will be
called or when a mutator has been explicitly overloaded. There is
nothing unacceptable about this.
Now, this is just wrong, at least in my environment - page 354:

"The ++$a operation can be autogenerated ... However, this does not
trigger the copying behavior that a real ++ operator would."

My ++ is autogenerated. If it did NOT cause copying then $a == $b
after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.

Likewise, again on page 357:
"$copy = $original; $copy = $copy + 1;
then no copying occurs ..."

Again, $copy is one more than $original, so copying certainly did occur.

No, you are mistaken. Copying DID NOT occur. Examine the
following lines carefully:

$a = $b;
++$a;

When the '++' operator is autogenerated, these lines are equivalent
to:

$a = $b;
$a = $a + 1;

which DOES NOT call the copy constructor. Instead, the function used
for overloading the '+' operator is called, which normally creates a
new object, populates that object from $a and 1, then returns that new
object, which then gets assigned to $a WITHOUT ever modifying $b. In
other words, no copy of $b was every made or needed (which is why I
said that you are mistaken when you claim that copying certainly did
occur).

Confusing? A little. That's exactly why I posted a write-up
explaining this exact issue. I even posted the title of this write-up
("Regarding copy constructors and mutators") to you, and even included
a link to it. It seems like you didn't read it, so I invite you to
read it again so that your confusion about this subject can be cleared
up. In case you missed the link the first time around, here it is
again:

http://groups.google.com/[email protected]

And if you want the exact excerpt that deals with this topic
(without having to look for it), here it is (paraphrased to fit your
example):


=== Beginnining of excerpt ===

The line:

++$a;

was treated as if it was:

$a = $a + 1;

making it so that the function used for '+', and not for '++', was
used. The
function used for '+' does NOT mutate (or change) any parameter passed
in. Instead, that method creates a new object, modifies its value,
and returns that instance. This mutates the new object but it doesn't
affect either of the values passed in. Because of this, '+' isn't
considered by Perl to be a mutator, so it will not call the copy
constructor (and will not give an error if a copy constructor doesn't
exist). It just simply creates a new object from $a and 1 and assigns
it back to $a, making $a lose its original object reference.

CLARIFICATION:
If '+=' is used on a shared reference when '+=' is OVERLOADED, it WILL
call the copy constructor. But if it is AUTOGENERATED (from '+'), it
WILL NOT call the copy constructor, because '+' has no need for one.

The same goes for '++'. If it's not overloaded, Perl is smart enough
to autogenerate by converting "$a++" to "$a = $a + 1" (which doesn't
need the copy constructor) to give you exactly what you'd expect.

=== End of excerpt ===


Basically, what Anno Siegel wrote in an earlier post was absolutely
correct:

So unless you plan to overload mutators, don't worry about it at all.
(There is nothing unacceptable about that.)
Maybe this mess will be fixed in Perl 6. Otherwise, there's always Java -
no such thing as a copy constructor, and no operator overloading.

Maybe this "mess" will be understood when you get around to reading
the write-up I posted (intended for the Perl community and anyone
confused (like I was) about "Copy Constructor Crazyness"). You are
one of the people I posted that write-up for, so please read it before
criticizing this aspect of Perl again.

Hopefully this will clear the issue for you.

-- Jean-Luc
 
J

Joe Smith

Unknown said:
"The handler for = is used in situations where a mutator (such as ++,
--, or any of the assigment operators) is applied to a reference that
shares its object with another reference."

It ought to be ""... where an explicitly overloaded mutator ..."

No, it happens for all mutators.
"The ++$a operation can be autogenerated ... However, this does not
trigger the copying behavior that a real ++ operator would."

My ++ is autogenerated. If it did NOT cause copying then $a == $b
after $a = $b; ++$a; Nope, $a is one more than $b when I run this code.

Likewise, again on page 357:
"$copy = $original; $copy = $copy + 1;
then no copying occurs ..."

Again, $copy is one more than $original, so copying certainly did occur.

The word 'copy' means something different.

You've got to remember that the equal sign creates a copy-on-write reference
to what is on the right hand side.

$b = 'z' x 1_000_000; # Create a string of one million asterisks.
$a = $b; # $a is a copy-on-write reference to $b's string.
$a .= 'z'; # This is a mutator. A copy of $a is created,
# then the copy gets a 'z' appended to it.
$a = $b; # Set $a back to a copy-on-write reference
$b .= 'y'; # A copy of $a is created, then $b gets modified.
$a = $b; # Back to the 1,000,001 character string.
$a = ':' . $a; # Create a new object (new string) and set its value.
$a = $b; # Back to the 1,000,001 character string.
$a = $a . 'w'; # Like the ':' case, a new object is created.
# The old object's value is used. This is
# not the same as using a copy of an object.

The overloaded '=' operator is called when a shared object is going to
be updated in place. There is a definite distinction between creating a
full-blown exact copy of an object versus duplicating an object's value.

$n++; # Is update-in-place; copy if needed before updating.
$n = $n + 1' # Not update-in-place; build a new object, add, store.

-Joe
 
U

Unknown Poster

The Camel authors may have their own idea, but I don't think there
is any argument about what the word "copy" means. The bottom line
is that Perl ALWAYS does object copying in the situations discussed in this
thread. The anomaly is, that for some bizarre reason, when you explicitly
overload "++" or another "mutator", you are forced to write a so-called
"copy constructor" by overloading "=".

To add to the fun, here's another whopper from page 357:
"The need for copying is recognized only by mutators ... If the operation
is autogenerated via +, as in: $copy = $original; $copy = $copy + 1;
then no copying occurs ..."

What operation? I think they might mean that a copy constructor is
autogenerated. Who knows?

Anyway, copying most definitely does occur if $copy and $original
are object references, and you (as you must) overload "++" to work
on objects of the class. This is not some magical, temporary copying
that only affects the "+ 1" line above. It's easy to demonstrate.
Simply change the value of either object after the addition, then
display the values. Since they differ, this proves that $copy
and $original now refer to two distinct objects. How'd that happen?
C-O-P-Y
 
A

Anno Siegel

Unknown Poster said:
The Camel authors may have their own idea, but I don't think there
is any argument about what the word "copy" means. The bottom line
is that Perl ALWAYS does object copying in the situations discussed in this
thread.

No. See below.
The anomaly is, that for some bizarre reason, when you explicitly
overload "++" or another "mutator", you are forced to write a so-called
"copy constructor" by overloading "=".

Yes. You *must* tell it how to make a copy of an object, if you want
it to protect an original from being changed along with the copy.
To add to the fun, here's another whopper from page 357:
"The need for copying is recognized only by mutators ... If the operation
is autogenerated via +, as in: $copy = $original; $copy = $copy + 1;
then no copying occurs ..."

What operation? I think they might mean that a copy constructor is
autogenerated. Who knows?

No, the "+=" operation. It can be autogenerated using "+". Now,
"+" doesn't need to protect its operands. Any reasonable implementation
of "+" will leave the operands alone and create a new object containing
the sum. So there's no need for the copy constructor.
Anyway, copying most definitely does occur if $copy and $original
are object references, and you (as you must) overload "++" to work
on objects of the class.

No, nothing is copied. Addition creates an independent sum object.

And where did you get that one *must* overload "++"?
This is not some magical, temporary copying
that only affects the "+ 1" line above.
Huh?

It's easy to demonstrate.
Simply change the value of either object after the addition, then
display the values. Since they differ, this proves that $copy
and $original now refer to two distinct objects. How'd that happen?
C-O-P-Y

Again, no. Your exasperation is getting tedious.

The copy constructor is only needed when an actual mutator method is
used to overload "+=" (or "++", or another potentially mutating operation).
A mutator method changes the content of a given object, as opposed to
creating a new object with modified content.

Only then, that is if "+=" is *explicitly overloaded* will the copy
constructor be called. It is not needed when "+=" is autogenerated.

Anno
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Unknown Poster
BTW, don't you just love the way you can "overload" a non-existent operator,
and get no error, no exception, no warning?

*I* do. This way I can easily write modules which work with different
versions of perl, which have different lists of overloadable operators.

But indeed, having something like

use overload strict => 1, '+0' => \&numify;

would be a good thing. Feel free to do this if you want to.

Yours,
Ilya
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top