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 gil on Tue Apr 12, 2011 7:20 am

Hi Erik

You could always expose a derived function by wrapping it in a traditional one. You could then use a trigger function or a property to rebuild the hash table. A simple example of what you are trying to do:

Code: Select all
:Class Hash

    :Field Public Instance Symbols

    ∇ setSymbols
      :Implements Trigger Symbols
      ⍝ Rebuild hash
      hashFn←Symbols∘⍳
    ∇

    ∇ r←Find obj
      :Access Public Instance
      r←hashFn,obj
    ∇

    ∇ new
      :Access Public Instance
      :Implements Constructor
      Symbols←⍬
    ∇

    ∇ new_1 symbols
      :Access Public Instance
      :Implements Constructor
      Symbols←symbols
    ∇

    hashFn←{}

:EndClass


And then to use it:
Code: Select all
h←⎕NEW Hash
      h.Find'me'
1 1
      h2←⎕NEW Hash
      h.Symbols←'me' (⍳6) h2 (2 3 4⍴⍳12)
      h.Find h2
3
      h.Find(⍳6)'me'
2 1
gil
 
Posts: 71
Joined: Mon Feb 15, 2010 12:42 am

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

Postby Erik.Friis on Tue Apr 12, 2011 6:50 pm

Thanks for your post Gil. What you are suggesting is essentially what I'm doing - the function that builds the hash table (returns a derived function) is in a namespace that gets included into my class. Each time a new symbol is added I recreate the derived function to build a new table. Then I can call the derived function at will to do fast look-ups. Like you did I had to assign the derived function to a global name in the class (I don't like this). The derived function cannot additionally be exposed by the class. Phil's method of placing the derived function in a namespace that's created inside the class gives one the most flexibility (thanks Phil) though it is not the kind of solution that should be considered a proper solution - it's more of a workaround.

What I ended up doing was this (preparing my code for when fields can accept a value of any class - notice the use of []EX and the field which is simply a "placeholder"):

Code: Select all
:class SomeClass

{comment} This namespace contains the function GetHash which takes a right argument of symbols and returns a
{comment} derived function which implements the hash table.  It's in a namespace so I can include it in classes
{comment} as needed.
:include #.Utlities
 
:field private MyHash
:field private MySymbolReferences<-0 2{reshape}0 {comment} [;0]=Symbols & [;1]=Data (objects)

{comment} N.B. That I always name my constructors after the class like in C++ and would like to see this become the
{comment} norm in Dyalog APL as we would no longer need the wordy line ":implements constructor" -- furthermore
{comment} I would like to see the ability to overload the constructor as opposed to the ungainly Construct1, {comment} Construct2, Construct3... I see in the documentation (yuck!).
 
{del}SomeClass
:implements constructor
:access public

  []EX 'MyHash'
  MyHash<-GetHash MySymbolReferences[;0]
{del}

{del}AddSymbol(Symbol Data)
  :access public

  MySymbolReferences,[0]<-Symbol Data
  MyHash<-GetHash MySymbolReferences[;0]
{del}

{del}r<-LookUp Symbol
  :access public

  r<-MyHash Symbol
{del}

.
.
.

:endclass


I'm somewhat happy with this solution for the time being, though I still cannot expose the hash table from the class using a property. As I write this it becoming clearer that I need to write my own hash table class and instantiate it within this class. Such an object can be exposed, but I would still like to see the name class restriction lifted on fields in general (seems like they special cased it just for objects).

Will try and post the code for the new class if I can figure out how! :)
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

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

Postby gil on Wed Apr 13, 2011 9:29 am

I see what you mean now. I'm not sure what led Dyalog to put a name class restriction on fields, perhaps this has something to do with .NET? Exporting a Dyalog class that has generic fields might cause issues when used outside APL?

At the moment only traditional functions can be exposed from a class as methods. Whether or not the restriction on fields can be lifted, I think it would be nice if one could declare any function as a method. If there was a key word :Method in addition to :Field you could declare it as:

Code: Select all
:Class UTF8File

    :Field Private Instance Text

    :Method Public Overridable Where←/∘⍳∘⍴⍨
    :Method Public Instance SaveAs←{
        tn←⍵ ⎕NCREATE 0
        r←(⎕UCS'UTF-8'⎕UCS Text)⎕NAPPEND tn 80
        ⎕NUNTIE tn
    }
...
:EndClass


Then again I don't know what the technical reason is behind the limitation to trad fns. I'm sure it's a good one ;)

As I write this it becoming clearer that I need to write my own hash table class and instantiate it within this class.


I don't know that Phil's method is much different to this. A namespace with the derived function within it would behave much like an instance of a hash table class with an exposed hash method. Maybe I misunderstood your statement?

Funny enough, I tested your code but changed the field MyHash to Public and it now allows me to see the derived function from outside, but gives me a VALUE ERROR when attempting to use it. I guess it still treats it as a data item rather than a function...
gil
 
Posts: 71
Joined: Mon Feb 15, 2010 12:42 am

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

Postby Phil Last on Wed Apr 13, 2011 12:52 pm

Then again I don't know what the technical reason is behind the limitation to trad fns. I'm sure it's a good one ;)

Given your suggestion re:
      :Method Public Instance SaveAs←{

I'm guessing it was lack of imagination.
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 Wed Apr 13, 2011 2:55 pm

@Gil: I really like your idea of having a :method keyword for dfns! I hope we see this in 13.1 I'm surprised that by making the field public that you were able to expose the derived function as I do an []EX on the variable. Can you please confirm?

@Phil: LOL! :)
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 Wed Apr 13, 2011 3:10 pm

Here's my HashTableClass that I'm pretty happy with:

Code: Select all
:class HashTableClass

    MyHash<-{}

    {del} HashTableClass x
        :implements constructor
        :access public

        Build x
    {del}

    {del} Build x
        :access public

        MyHash<-x{jot}{iota}{jot}{({enclose}{power}(1={depth}{omega})){omega}}
    {del}

    {del} r<-Hash x
        :access public

        r<-MyHash x
    {del}
:endclass


Gil's idea of being able to change the third line to:

Code: Select all
    :method public MyHash


is a fine suggestion! I wanted to have Build actually return the derived function to expose it, but I get a SYNTAX ERROR when I try to access it from outside the object. Internally to the object the function runs fine.

I don't like the idea of using the global name inside the class (MyHash), but I like Gil's suggested initialization of the name to {} as a pseudo declaration.

Comments on the class are welcome!
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

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

Postby gil on Wed Apr 13, 2011 5:05 pm

I'm surprised that by making the field public that you were able to expose the derived function as I do an []EX on the variable. Can you please confirm?


Try this:
Code: Select all
:Class Hash

    :Field Public Instance MyHash

    ∇ new
      :Access Public Instance
      :Implements Constructor
      ⎕EX'MyHash'
      MyHash←(⍳5)∘⍳
    ∇

:EndClass


Now in the session:
Code: Select all
      h←⎕NEW Hash
      h.MyHash
VALUE ERROR
      h.MyHash
     ∧
      ⎕NC'h.MyHash'
0
      )ed h.MyHash


For some reason auto-complete kicks in and I can see the composed function in the editor but I can't use it from outside the instance. Bug?
gil
 
Posts: 71
Joined: Mon Feb 15, 2010 12:42 am

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

Postby Erik.Friis on Wed Apr 13, 2011 5:43 pm

Gil,

The VALUE ERROR makes sense because after expunging the field the new name is private by default. It seems that, for better or worse, the editor allows you to edit private members of an object from outside of the object. As good as it is, it would seem that there are perhaps a few loose ends with the editor as well.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

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

Postby gil on Wed Apr 13, 2011 5:58 pm

I don't like the idea of using the global name inside the class (MyHash), but I like Gil's suggested initialization of the name to {} as a pseudo declaration.


Thinking about it I guess what actually happens is that you end up with a private shared version of MyHash that isn't used anywhere and an additional private instance version that is used by the Hash method.

Can't take the credit for the pseudo declaration though, saw it somewhere recently in Kai's code (used inside a dfn setting up a ⎕NA call). In this context it's perhaps misleading more than anything as you get the false impression that it's getting redefined when in fact it coexists (one shared and one instance version, both with the same name).
gil
 
Posts: 71
Joined: Mon Feb 15, 2010 12:42 am

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

Postby gil on Wed Apr 13, 2011 6:04 pm

Erik.Friis wrote:Gil,

The VALUE ERROR makes sense because after expunging the field the new name is private by default. It seems that, for better or worse, the editor allows you to edit private members of an object from outside of the object. As good as it is, it would seem that there are perhaps a few loose ends with the editor as well.


If it were private the auto-complete wouldn't suggest it (try changing it to a private field and it will be hidden). Then again you're right about the editor still allowing you to view the content. I think I like that as it makes development and testing a lot easier. the VALUE ERROR would still stop you from executing code that refers to private content, but inspecting it without having to step into the object is handy.
gil
 
Posts: 71
Joined: Mon Feb 15, 2010 12:42 am

PreviousNext

Return to Object Oriented Programming

Who is online

Users browsing this forum: No registered users and 1 guest