Initialize a Field In-Line or Within a Constructor?

Writing and using Classes in Dyalog APL

Initialize a Field In-Line or Within a Constructor?

Postby Erik.Friis on Mon Apr 04, 2011 6:42 pm

C++ does not allow you to initialize a class member variable other than in a constructor. I do find it convenient to do:

:field private MyField <- 0

as opposed to doing it in the constructor, because it's easy to see your field initial values at a glance. I tend to use this notation for simple initializations as I'm not totally clear on what sorts of APL expressions can be placed in a class outside of a field or member function. I find myself having to put []IO<-0 as the first line of my classes which I don't really like to have to do - I don't know the full rules about code in the main class definition and I'm not sure whether I like or dislike that you can put expressions there yet. The documentation said that some expressions get run when the class is fixed which I wasn't too clear on and haven't had time to play with to understand in more depth.....the mixture of static scoping and dynamic scoping relating to a class can be a bit confusing sometimes and I was also surprised that I needed to do []NEW #.NullClass inside my classes and that I could not do []NEW NullClass, but OK. Perhaps it would have been nice to only do static scoping inside class definitions as I think the initial choice of dynamic scoping in APL to have been a poor choice.

So can someone give a clear explaination of when to initialize a field in-line as opposed to in the constructor and what are the performance benefits/penalties. Any other caveats are appreciated as I'm relatively new to OOP in APL.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Initialize a Field In-Line or Within a Constructor?

Postby DanB|Dyalog on Mon Apr 04, 2011 8:01 pm

Eric,
when a class or namespace is being defined ([]FIXed) with a script a new namespace is created and each line in the script is run in sequence INSIDE the new namespace.
Lines like
:field VarX <- X
are executed like the others and the variable created (with the value of X here) .
You can of course define VarX to be a field (or a regular variable) and delay its definition later, perhaps in the constructor.

As with any namespace's new definition and any fn for that matter, you may wish to set your system vars if it is important to you, otherwise you'll inherit whatever value they have in the defining environment.

This is a good way to prepare your class. You could, for example, define a variable/field's value from file or the registry.
Remember that because you are IN the namespace, trying to access objects outside the namespace in which you are executing statements will require the use of # or ## (or []SE) to access them. In doing
Inst <- []NEW Class
you will need the path to your Class unless it is PREVIOUSLY defined in the same space (a nested class) ABOVE the line you are executing.

An exception to this is :Include NAMESPACE which assumes the NAMESPACE to be at the ## level.

Here is an example:
[]IO<-1
:namespace Utils
...
:endnamespace
====================
:class outside
...
:endclass
===================
:class MyExample
⍝ at this point []IO is the same as in the class where this is being defined (1 here)

:include Utils ⍝ Utils is picked up in the same space as we are defining this class

:class inside ⍝ define a local (nested) class
...
:endclass

[]IO<-0 ⍝ redefine []IO in this class
:field io←⎕new ##.outside ⍝ create a field from an outside class
ii←⎕new inside ⍝ create a variable from a nested class (inside this class)

:endclass

Does it make sense?
DanB|Dyalog
 

Re: Initialize a Field In-Line or Within a Constructor?

Postby DanB|Dyalog on Mon Apr 04, 2011 8:19 pm

Pros and cons of initializing variables in the class or the constructor.

Variables initialized at []FIX time are for the class, those initialized in the constructor are for the instance.

You can initialize a class' variable (field) in the constructor IF and only if its the value will always be the same.
In that case it is better to have it done only once (when the class is fixed) otherwise it will be done every time an instance is created.
Apart from the fact that CPU time WILL be equal (done once) or greated (done >once) if done in the constructor, it is cleaner to do it in the class (and less confusing perhaps).
DanB|Dyalog
 

Re: Initialize a Field In-Line or Within a Constructor?

Postby Erik.Friis on Tue Apr 05, 2011 4:34 pm

DanB|Dyalog wrote:You can initialize a class' variable (field) in the constructor IF and only if its the value will always be the same. In that case it is better to have it done only once (when the class is fixed) otherwise it will be done every time an instance is created.


Dan, Thanks for your replies. OK, that clears things up a bit regarding being done once at Fix time vs. when an instance is created. But I'm a little confused about your statement above. If an initial value of a field would be the same for each instance of the class would it not be better to define it in-line in the field definition as opposed to in the constructor? Your statement above seems to be saying it should be done in the constructor.

Code: Select all
:class Foo

:field private MyField<-5

{del}Foo
   :implements constructor
   :access public
{del}
:endclass


as opposed to:

Code: Select all
:class Foo

:field private MyField

{del}Foo
   :implements constructor
   :access public

   MyField<-5
{del}
:endclass
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Initialize a Field In-Line or Within a Constructor?

Postby Erik.Friis on Tue Apr 05, 2011 4:50 pm

Additionally I'm not too clear on the namespace stuff. Let's say I define this class:

Code: Select all
:class Foo
   []<-'Hello, world!'

   :field private MyField<-5

   []<-z<-{iota}5

   {del}Foo
      :implements constructor
      :access public
   {del}
:endclass


When I fix the class I see "Hello, world!" and "0 1 2 3 4" being printed to my screen.
There is a namespace called Foo that I can )CS too. I would have expected the variable z to be there, but it is not! )fns, )vars, )methods returns nothing in the namespace. It would have been nice to see Foo displayed in response to )methods. There is no )fields, but that would have been nice to display MyField. The whole script/namespace thing is very confusing. It seems to me that a class could have been implemented as a special type of namespace (I know they behave a bit differently - everything in a namespace is public - like the difference between classes and structures in C++) where I can work on my methods and fields just as if you were in a namespace without having to necessarily resort to the script editor.

So where did z go? Does it only exist to be executed in the context of the namespace and then disappear? How can you see your fields and methods when you are in the namespace?
Last edited by Erik.Friis on Tue Apr 05, 2011 7:42 pm, edited 1 time in total.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Initialize a Field In-Line or Within a Constructor?

Postby paulmansour on Tue Apr 05, 2011 5:25 pm

When Dan wrote:

"You can initialize a class' variable (field) in the constructor IF and only if its the value will always be the same."

I think he meand to say "You can initialize a class' variable (field) in the CLASS IF and only if its the value will always be the same."

Another way to think of it is:

Initialize a field in the class definintion when its starting value for all instances is the same literal.

I use "literal" here because is is easy to have a function that returns a constant (a long file path say, or a complex trap statement) and to call this function in a class to initialize a field. It is then easy to make a change to this function and to be under the false impression you are changing your class, when in fact the function will not be executed again until you refix the class.
paulmansour
 
Posts: 420
Joined: Fri Oct 03, 2008 4:14 pm

Re: Initialize a Field In-Line or Within a Constructor?

Postby Erik.Friis on Tue Apr 05, 2011 6:33 pm

Thanks Paul, That makes sense....I thought perhaps it was a typo but wasn't sure. Any ideas on the namespace stuff??
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Initialize a Field In-Line or Within a Constructor?

Postby Phil Last on Tue Apr 05, 2011 7:23 pm

Your assignment to "z" without declaring it as a public field means it defaults to private. You can only see it at run-time from within the operations defined inside the class: the methods and any other functions or operators within the class that are called by the methods. I think.
User avatar
Phil Last
 
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: Initialize a Field In-Line or Within a Constructor?

Postby DanB|Dyalog on Tue Apr 05, 2011 9:26 pm

Erik.Friis wrote:Additionally I'm not too clear on the namespace stuff. Let's say I define this class:

Code: Select all
:class Foo
   []<-'Hello, world!'

   :field private MyField<-5

   []<-z<-{iota}5

   {del}Foo
      :implements constructor
      :access public
   {del}
:endclass


When I fix the class I see "Hello, world!" and "0 1 2 3 4" being printed to my screen.
There is a namespace called Foo that I can )CS too. I would have expected the variable z to be there, but it is not! )fns, )vars, )methods returns nothing in the namespace. It would have been nice to see Foo displayed in response to )methods. There is no )fields, but that would have been nice to display MyField. The whole script/namespace thing is very confusing. It seems to me that a class could have been implemented as a special type of namespace (I know they behave a bit differently - everything in a namespace is public - like the difference between classes and structures in C++) where I can work on my methods and fields just as if you were in a namespace without having to necessarily resort to the script editor.

So where did z go? Does it only exist to be executed in the context of the namespace and then disappear? How can you see your fields and methods when you are in the namespace?



All the lines were executed. You cannot see 'z' because it is private but it is there, available only inside an instance.
To convince yourself insert a public method and trace thru it. You will see everything inside the instance.
You can still )CS into the class/instance but you won't see anything. You can only "see" what's available there thru the system fn []NL, e.g. []NL-2 3.
[]NL will only show you the public members. The concept of encapsulation is well implemented, you really can't see private members inside a class.
/Dan
DanB|Dyalog
 

Re: Initialize a Field In-Line or Within a Constructor?

Postby Erik.Friis on Tue Apr 05, 2011 9:39 pm

OK so there is no difference between simply assigning a variable and using a :field private tag - that is not made clear enough in the documentation:

x←5
:field private y←5

are of the same nameclass and act the same? I guess I would have expected x to have dynamic scope and y to have static scope to remain more consistent with the core language. Interesting that []nl 2 inside the class will report x & y and that []nl -2 is not required. This part is still a bit confusing to me.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Next

Return to Object Oriented Programming

Who is online

Users browsing this forum: No registered users and 1 guest