The Need for Copy Constructors

Writing and using Classes in Dyalog APL

The Need for Copy Constructors

Postby Erik.Friis on Thu May 05, 2011 8:04 pm

It is becoming painfully obvious to me that there is a real need to be able to define a copy constructor for a class. True you can write a Clone or Copy member function when needed, but the aestetics are compromised and it's very easy to get unintended functionality when you assign one object to another variable either by using the assignment arrow or by passing it as an argument.

This predicament also led me to another discovery in that when writing a Clone/Copy member function:

{del}r<-Clone
:access public

r<-#.[]NEW #.MyClass
.
.
.
{del}

You must prefix the []NEW with #. otherwise you will get a "nested" (?) object even when returned outside the class by the member function. I'm not sure if this is proper behaviour or not as it was totally not what I expected and it's made me rethink about how I'm creating objects inside classes as often you do not want the extra baggage with your object.

I was getting a resulting reference of:

#.[MyClass].[MyClass]

and I wanted:

#.[MyClass]

Anyone care to chime in here........???
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: The Need for Copy Constructors

Postby Phil Last on Fri May 06, 2011 7:29 am

Classes, instances and GUI objects are all nss. Each ns is "rooted" to the ns wherein the ⎕NS, ⎕NEW or ⎕WC that created it was run except in the cases of ⎕WC or ⎕NS being given a fully qualified name as left argument. You say you need to prefix ⎕NEW with "#.". Others might not want to. The ability to do ## in your code and look "up" the ns-tree is often of great benefit.

So far as I am aware the design of APL# has exactly what you want in that nss will not "remember" where they were created and programmers will have to invest them with whatever hierarchical information they will require when they are created.

So where you need to enhance ⎕NEW to forget the instance's history, in APL# the opposite will often be needed.
User avatar
Phil Last
 
Posts: 549
Joined: Thu Jun 18, 2009 6:29 pm

Re: The Need for Copy Constructors

Postby Erik.Friis on Fri May 06, 2011 1:17 pm

Hi Phil,

I guess I was not really aware of this "rooting" until I wrote a method to make a copy of an object and this is where it caused "problems" since the copy does not want to retain the history from whence it came per se. I can see where using ## can be handy in some cases, but in a lot of my code I pass references to access other objects even in a particular objects hierarchy. I guess coming from OO programming in C++ I just wasn't expecting the current behaviour. From an implementation point of view how is this hierarchical baggage stored in the internals of the object...is it just a single pointer or an array of pointers? Not sure I want to carry all of this excess baggage around in every object.

By the way, even if copy constructors were implemented (e.g. :implements copy constructor) there is still the need to override this behaviour and this is where it gets tricky. I'm still trying to mull this over as I have not found a "one size fits all" solution yet.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: The Need for Copy Constructors

Postby Morten|Dyalog on Sat May 07, 2011 7:46 am

Erik wrote:I'm still trying to mull this over as I have not found a "one size fits all" solution yet.


I think you will mull for a long time, I don't believe that there exists a "one size fits all" solution. This is the main reason why we have not attempted to implement a primitive mechanism for cloning. Can you point to other languages that implement a general cloning mechanism, I'd be interested to read how this is done? I think you'll find that they generally leave it up to the class implementor to define how cloning of instances of his class must be done.

Aside: How would you express the copying of an object in APL? I don't think we have a suitable primitive function.

The "obvious" thing to do would be to create a new instance where you had copied the contents of all declared fields, but this is only the right thing to do in very simple cases. For any object references within the object, it is not clear whether the references should be copied or a "deep" copy should be performed - only the class implementor knows.

APL doesn't spend any "energy" remembering where an object is created. In Dyalog APL, namespaces (and that includes objects, which are "special namespaces") are not just names, they are "containers" into which functions and variables are ("physically") placed. The "parent" of an object in Dyalog APL is quite simply the namespace in which it "exists", because it was created there. What matters is WHERE ⎕WC or ⎕NEW were executed:

      NS1.OB1←#.⎕NEW blah ⍝ OB1 is a reference in NS1 to an object which "is" in the root
#.OB2←NS1.⎕NEW blah ⍝ OB2 is a reference in the root to an object which "is" in NS1

I believe that the reasons it was done this way is essentially that the GUI implementation was done first, namespaces were added later and objects came along at the end.

Note that a reference to an object in a namespace will keep the entire namespace "alive". If we follow the above with (⎕EX 'NS1'), then although the name NS1 will no longer exist, the namespace will continue to exist "anonymously" for as long as OB2 is a reference to something that is inside the namespace. People often experience this by leaving a global reference to a child of a form around in a variable (#.TheGrid←MyForm.Grid), and are surprised that the form does not go away on (⎕EX 'MyForm').

Also note that the location where an object is created decides how it inherits properties from its parent - like the setting of ⎕IO.
User avatar
Morten|Dyalog
 
Posts: 388
Joined: Tue Sep 09, 2008 3:52 pm

The Need for a ultimate definition

Postby giangiquario on Mon May 09, 2011 9:33 am

Morten wrote:
Aside: How would you express the copying of an object in APL? I don't think we have a suitable primitive function.


I need a ultimate and consistent definition of object in APL. It has now too many meanings.
We cannot forget the lesson of Ken Iverson:

The importance of nomenclature, notation, and language as tools of thought has long been recognized.
User avatar
giangiquario
 
Posts: 46
Joined: Thu Nov 26, 2009 8:55 am
Location: Milano, Italia

Re: The Need for Copy Constructors

Postby Erik.Friis on Mon May 09, 2011 2:15 pm

I need a ultimate and consistent definition of object in APL. It has now too many meanings.


I tend to agree. Though the laguage designers did an amirable job in trying to marry the legacy GUI objects, namespaces, and classes, the current implementation is confusing and I believe more complicated than it need be. I think that perhaps an opportunity was missed for a simple unification of namespaces and classes -- instead of the current scripting, a class could simply be defined in a namespace. It would require some syntactical enhancements for defining fields, properties, et al., but methods as functions, dfns, and defined operators would simply be defined in the normal way. You would be able to do a []NEW on this kind of a namespace, you'd get a DOMAIN ERROR if you did it on non-class namespace. I don't see the need to create a namespace per se when an object is created and I think the idea of the "surrounding namespace" should go away. Typing )OBS and getting a list of your namespaces, classes, and objects is confusing at best...an object should be just that -- an object, not a namespace and when I type )OBS I should get a list of my objects. )CLASSES should list my namespaces that are "special cased" as classes.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: The Need for Copy Constructors

Postby Morten|Dyalog on Mon May 09, 2011 8:00 pm

giangiquario wrote:I need a ultimate and consistent definition of object in APL. It has now too many meanings.


To me, an "object" is a container into which names that refer to APL variables, functions and operators can be placed. Dyalog APL recognises three fundamentally different types of objects: Namespaces, Classes and Instances. But I think you already know this, so I'm not 100% sure what kind of answer you are looking for. Can you explain a little more about the "many meanings" that you believe the word "object" currently has (apart from the fact that "object" is a very general word in the English language, so people feel tempted to call arrays and functions "objects" too).

In Dyalog APL, arrays can contain "references" to objects. References (and objects) *ARE* in many ways alien to the core of APL, which is a notation designed to deal with the VALUES and not POINTERS. However, in my opinion, marrying the two paradigms has been worth the effort and the fact that we end up with a small number of "inconsistencies". The alternative would be to force people to learn C# or Java in addition to APL - and this would still not deliver the power that current Dyalog APL gives us to work on arrays of objects. In fact, I would go as far as to say that the successful combination of the paradigms is THE main reason why Dyalog APL has been a successful development tool for the last decade.

The point I was making in my previous posting was that we have no notation to "copy" the object that a reference is pointing to. (2⍴ref) and (2/ref) both simply copy the reference, so you end up with two references to the same object. (2↑ref) will create a new instance of the class as a "fill element", IF the class has a niladic constructor. I can't see a "natural" way to extend APL to express "cloning" of an object. On the other hand, I don't know of other programming languages that provide a primitive "clone" either; they tend to leave it to the class to define a method called "Clone" (but this could be due to ignorance on my part)?
User avatar
Morten|Dyalog
 
Posts: 388
Joined: Tue Sep 09, 2008 3:52 pm

Re: The Need for Copy Constructors

Postby Morten|Dyalog on Mon May 09, 2011 8:09 pm

Erik.Friis wrote:I think that perhaps an opportunity was missed for a simple unification of namespaces and classes -- instead of the current scripting, a class could simply be defined in a namespace.


Perhaps it would have been (or is still) possible to come up with a class definition that does not require a script - but I don't see how this fundamentally changes anything about the different types of objects supported by the language. You would still have three kinds of objects: non-class namespaces, class namespaces (which, if you modiy them, should affect all existing instances), and instances - exactly the same as now.

The "surrounding namespace" is a bit odd (but also sometimes very useful), its existence was dictated by historical reasons related to supporting objects that are actually defined outside APL (GUI, COM and .NET objects).

)OBS listing everything *is* not very helpful, we'll think about that for v13.1, perhaps.
User avatar
Morten|Dyalog
 
Posts: 388
Joined: Tue Sep 09, 2008 3:52 pm

Re: The Need for Copy Constructors

Postby giangiquario on Thu May 12, 2011 12:43 pm

)OBS list global namespaces only.
Morten:
To me, an "object" is a container into which names that refer to APL variables, functions and operators can be placed. Dyalog APL recognises three fundamentally different types of objects: Namespaces, Classes and Instances.


The meaning of an APL object had a sweeping change.
It looks like that objects are namespaces, classes and instances only.

Maybe my understanding is cramped by my knowledge of english.
For me an APL object is something that takes possession of a slice of storage and is related to a name such
that []NC 'name' returns a correct result.

The APL language reference says in "Size of Objects":
If the name in Y identifies an object with an active referent, the workspace required in bytes by that object is returned...

ALSO vars fns ops are APL objects.

I can clone vars fns ops.
An instance owns a chunk of memory.
I have a question (it is not a criticism): Why is it impossible to replicate that sequence of bytes?
User avatar
giangiquario
 
Posts: 46
Joined: Thu Nov 26, 2009 8:55 am
Location: Milano, Italia

Re: The Need for Copy Constructors

Postby Budgie on Fri May 13, 2011 4:54 pm

I think this is getting away from the subject, which is Copy Constructors.

When I decided to learn about OO in APL, I decided to rewrite an application that was ideal for objects. This application deals with five different objects, each of which was previously stored as a nested array, and all but one of which was duplicated at some time in its lifetime.

During the conversion I had to decide how to perform this object duplication. Obviously the use of ⎕NEW was required, and the right argument of the constructor was an object of the same class as the copy we are making. Once the constructor decides that a copy is to be made, it then needs to assign the values of all the fields in the original object into the same fields in the new object (this is equivalent to a deep copy). The problems arise when we are copying a private field, as you can't read it direct, and you have to set up a property with a "getter" for each field, which can be a bit of a pain if there's a lot of them.

So I would like to see an ":implements copy constructor" statement which allows the function to get hold of private fields from the object that is its left argument and which is of the same class as the one being constructed.

But I can live without it ...
Jane
User avatar
Budgie
 
Posts: 36
Joined: Thu Nov 26, 2009 9:22 am
Location: Beckenham

Next

Return to Object Oriented Programming

Who is online

Users browsing this forum: No registered users and 1 guest