Initialize a Field In-Line or Within a Constructor?

Writing and using Classes in Dyalog APL

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

Postby DanB|Dyalog on Wed Apr 06, 2011 11:28 am

Erik.Friis wrote: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.


There is a slight difference but only in []NC: x is 2.1, and y is 2.2 to tell the difference but otherwise yes, they are both privante instance members.
DanB|Dyalog
 

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

Postby Erik.Friis on Wed Apr 06, 2011 1:49 pm

Thanks Dan. OK finally read up on the decimal extensions and negative values. I guess treating "x" in the same manner as a field is fine as it's simpler than having one variable dynamically scoped and one statically scoped. Actually in a class these variables are both dynamically & statically scoped -- static outside of the class and dynamic within. I appreciate your clarification.
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 Sat Apr 09, 2011 1:32 am

Dan, There is at least one major difference that I have found between a :field and a simple variable. I created a function that returns a derived function using compose. If I try and assign the resultant derived function to a field I get a SYNTAX ERROR. If I assign it to a variable not using :field it works as expected. The scope of :field may be too tight, as I can of course assign a reference to a field, why not a derived function?
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 Sun Apr 10, 2011 7:07 am

A field can only contain data (class 2 or 9). So does a variable (by definition). When you do
X<- +/
you are defining a function and assigning it to the name X which has no value yet. If X is already defined as a variable (or space) this will fail, just like a field, with a SYNTAX error. When you use :FIELD you are telling APL that the name to be defined will hold data; trying to assign a fn to it subsequently fails.
Spaces (refs) are data, not code, hence the reason why they are accepted in :FIELDS. Be aware though that assigning a ref to a field will see all instances with the SAME ref just like the same value if a non-ref was assigned. This may not be what you want. To ensure a different ref you must use the constructor.

Derived fns cannot have permissions (nor can dfns or operators). If you wish to allow this code to be SHARED or PUBLIC you have to use a Tfn for that and use the :ACCESS statement within it.
DanB|Dyalog
 

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

Postby Erik.Friis on Sun Apr 10, 2011 11:09 pm

Hi Dan,

Well I guess that explains the SYNTAX ERROR though I cannot help, but feel that the current implementation can be improved. A field should be able to hold any entity, not just a value ([]NC=2) and an object ([]NC=9). After all, an object is not just data, but data and functions and more. When you assign an object to a field (or variable) as you well know only the reference (pointer) is assigned. When I do x<-+/ a pointer to the derived function is also assigned to x, x is not really a function, but an alias to a function. Since I can write a normal function to return a derived function, it seems awefully unnatural (and restrictive) that I cannot do it with a member function and a property in a class. It also goes against the grain of APL to force such a strict binding between x and the function in an expression "x<-some_fn". So if x was assigned "0" first that I cannot assign a reference to "+/" afterwards (assign is in it's own syntactic class and as such this should not pose an issue). I can assign an object or class after the fact to x that was set initially to 0. This restriction will need to be resolved at somepoint as x<-+/ is a first step in the direction of function arrays (a function scalar) actually and will have profound effects on what will be possible when general arrays become general enough to enclude function references which I feel are the current missing half of APL.

My last point is this, in a strongly typed language like C++ a field/variable can only hold an "object" of the type that it's declared as. APL being untyped should allow a field or variable to hold an "object" of any name class and that variable should be freely reassignable at any point.
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 Mon Apr 11, 2011 1:51 pm

Here's an example of where this restriction caused a problem for me. I have a class where objects are associated with a unique symbol. I wanted a faster way to select the appropriate object based on a symbol than using Dyadic iota. Ok so I created a method that would create a hash table internally by returning my vector of symbols composed with iota. This derived function I only want to build every time a new symbol is added and keep around and such I wanted to save it to a field so that I could use it in various member functions of the class or even pass it outside with a property. No can do! I had to assign it to a non-class unused name and rely on the static scoping of the class. I still can't pass it outside the class with a property. I basically got it working using a global name within the class, but I don't consider this a clean implementation of what I was trying to achieve.
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 Mon Apr 11, 2011 6:21 pm

Erik,

I must confess I haven't tried this but if I do
      ns←⎕ns''
ns.sum←+/

I might be able to do
      :Field sum←ns


I know this isn't exactly what you want but if it works, and I see no reason why not, it might point the way to a solution.
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 Erik.Friis on Mon Apr 11, 2011 8:28 pm

Hey Phil! Nice to see you again! Clever approach to put the derived function in a namespace. Funny that a field will accept a namespace (which is essentially a mini workspace), but not a derived function :) Unfortunately in this case you would need to have that extra level of indirection: sum.sum 1 2 3, but not a bad compromise. You can also []EX 'Sum' and then do Sum←+/, but that's similiar to just assigning it to a global variable (name) and you still can't pass it out of the object with a property (I tried). So I suppose yours is the most workable solution until (if) they ease up on the restriction. Bottom line is that until a field is assigned it should have a nameclass of 0, not 2 (just like a localized name in a function!
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 11, 2011 10:39 pm

Erik.Friis wrote:Here's an example of where this restriction caused a problem for me. I have a class where objects are associated with a unique symbol. I wanted a faster way to select the appropriate object based on a symbol than using Dyadic iota. Ok so I created a method that would create a hash table internally by returning my vector of symbols composed with iota. This derived function I only want to build every time a new symbol is added and keep around and such I wanted to save it to a field so that I could use it in various member functions of the class or even pass it outside with a property. No can do! I had to assign it to a non-class unused name and rely on the static scoping of the class. I still can't pass it outside the class with a property. I basically got it working using a global name within the class, but I don't consider this a clean implementation of what I was trying to achieve.


Maybe I don't understand but what is wrong with using a method (a fn, that's what they're for)? Why insist on using a field to do the job of a method?
What am I missing? A SHARED method would use a shared field's data (your instances' symbols) which it would use (composed with iota to get your hash table) to do the job.
Can you show your code so we can comment?
DanB|Dyalog
 

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

Postby Erik.Friis on Mon Apr 11, 2011 11:51 pm

I only want to build the hash table when the keys (symbols) change (i.e., I add a new symbol) - if you have to build the hash table from scratch each time you use it then it doesn't make sense to use one and I would just resort to the slower dyadic iota. Once the compose is performed with the data and iota (the hash table is built in memory), I need to store it somewhere. Can't put it in a field which is the logical place to put it because its (reference) is in the form of a derived function (data jot iota) which makes sense. Phil's idea works, but is somewhat ungainly. Currently I am resorting to assigning it to a global (in the class) name - which has even more restrictions (can't expose it through a property). Can't post code right now as I'm typing on an iPad :(
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

PreviousNext

Return to Object Oriented Programming

Who is online

Users browsing this forum: No registered users and 1 guest