Improper Behaviour From Arrays of Objects?

Writing and using Classes in Dyalog APL

Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Tue Apr 12, 2011 11:59 pm

I defined the following class:

Code: Select all
:class FooClass
    {del}Print x
        :access public

        []<-x
    {del}


And was interested to see the behaviour of arrays of objects when calling the method Print.

Code: Select all
     Foo<-[]new #.FooClass

     Foo.Print 'Hello'
Hello

{comment} OK this is expected!

     (Foo Foo).Print 'Hello'
LENGTH ERROR

{comment} OK, makes sense to me -- I like it!

     (Foo Foo).Print {enclose}'Hello'
Hello
Hello

{comment} This is great!

     (,Foo).Print {enclose}'Hello'
Hello

{comment} Still lookin' good!

     (,Foo).Print 'Hello'
H
e
l
l
o

{comment} What?!?!  This can't be right - can it?



OK if this is going to scalar extend the 1-element vector and apply it to each element of the vector 'Hello' then by definition (Foo).Print 'Hello' must do the same thing as should Foo.Print 'Hello'. The current behaviour of Foo.Print 'Hello' is the most reasonable, thus the result of (,Foo).Print 'Hello' is wrong -- they must match. To get the errant behaviour (an implied each) the expression Foo.Display{each}'Hello' should be employed. The result of the last expression should be LENGTH ERROR!

I'd be curious as to others' opinions on this.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Improper Behaviour From Arrays of Objects?

Postby Phil Last on Wed Apr 13, 2011 10:14 pm

I'd be curious as to others' opinions on this.

It's not restricted to the object framework but a feature of the namespaces on which it was built:
      (,#).{⎕←⍵}'Hello'
H
e
l
l
o

I """think""" it's right though it doesn't look it at first glance. I've done enough with running transient functions in multiple namespaces that I'd have thought it would have broken my code by now if it was inconsistent. But I'd rather sleep on it before committing myself.
User avatar
Phil Last
 
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Thu Apr 14, 2011 1:52 am

OK Phil that expression you posted gives me a headache -- I better pour a pint and think about that one! :)

If it was built on the namespace baggage then that may be wrong in this case. One of the more well versed APL theorists should be able to provide the rank of the various components of the expression and tell us why or why it should not behave in that fashion. I feel there can be a better unification of classes, object, and namespaces, but that may mean undoing some things they did with "old" namespaces, which may be difficult, though necessary to get things right.

P.S. Arrays of functions/operators, the "holy trinity" of operators: rank/axis/depth, and automatic rank-n extension are next ;)
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Thu Apr 14, 2011 2:09 am

Code: Select all
      (,#).{⎕←⍵}'This' 'looks' 'wrong'
This
looks
wrong
      (⊂,#).{⎕←⍵}'This' 'looks' 'wrong'
T
h
i
s
l
o
o
k
s
w
r
o
n
g
      (⊂⊂⊂⊂,#).{⎕←⍵}'This' 'looks' 'wrong'
T
h
i
s
l
o
o
k
s
w
r
o
n
g
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Improper Behaviour From Arrays of Objects?

Postby JohnS|Dyalog on Thu Apr 14, 2011 9:43 am

I think there are two issues in play here:

[0] For "historical reasons", there is a discontinuity between dotting a depth-0 ref and any other array of refs, as the following sequence shows:

      v←'hello'
#.v ⍝ 5-vector
hello

(2 3⍴#).v ⍝ 2 3-matrix
hello hello hello
hello hello hello

display¨ (#).v (,#).v
┌→────┐ ┌→────────┐
│hello│ │ ┌→────┐ │
└─────┘ │ │hello│ │
│ └─────┘ │
└∊────────┘

To be consistent, #.v should produce a scalar (enclosed) result. However, being able to "dot" an array of refs appeared in Dyalog some time after being able to dot a simple scalar ref, and so making this change would (a) have broken a lot of code and (b) may not be desirable anyway.

[1] With arrays of instances of objects, it seems desirable to be able to "dot" functions within the instances. A cut-doun example might be:

      (# #).⌽ ...

There are two implementation choices:

- Pass the whole of the argument array to each ref'd function.
- Distribute the items of a conformable argument among the ref'd functions.

The latter choice is more general as we can trivially emulate the former by enclosing the argument. So that's the one we chose:

      (# #).⌽'hello' 'world'      ⍝ distributed arg items
olleh dlrow

(# #).⌽⊂'hello' 'world' ⍝ whole arg array passed to each ref'd function
world hello world hello

So this is what's happening with Phil's example:

      (,#).{⎕←⍵}'Hello'

The 1-vector (,#) is conformable with the 5-vector 'Hello' and so the function is distributed and applied five times. Had Phil typed:

      ( #).{⎕←⍵}'Hello'

The function would have been called just once.

Note that with a dyadic function application, we need 3-way conformability between the left-argument, ref-array and right-argument.
JohnS|Dyalog
 

Re: Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Thu Apr 14, 2011 2:07 pm

Hi John,

Nice to see you again! I follow your argument until you get to the statement:

The 1-vector (,#) is conformable with the 5-vector 'Hello' and so the function is distributed and applied five times.


I can understand that a scalar expression would extend (conform) to a 5-vector and be applied 5 times (and I can understand why this was not done with the dot notation), but I see no reason why a 1-vector would do so. It seems to me that the most reasonable result from such an expression would be a LENGTH ERROR. The rank-0 application is more logically handled with an each (#.{[]<-w}"'Hello'). The thing that further surprised me is that ,# and {enclose},# and ({enclose}{power}n),# all yield the same result. I understand why a simple scalar has infite (0) depth, but (,#) is neither simple nor a scalar.

Additionally it seems that ({enclose},#){match}{enclose}{enclose},# properly returns a 0.
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Improper Behaviour From Arrays of Objects?

Postby Phil Last on Thu Apr 14, 2011 4:22 pm

I'm afraid we're nearly 50 years too late to expect a one-item vector not to behave like a scalar except in the presence of another scalar. Sometimes a length error would seem appropriate but it just doesn't happen. Tell a lie!:
      1,2 3⍴⍳4
1 0 1 2
1 3 0 1
(,1),2 3⍴⍳4
LENGTH ERROR
(,1),2 3⍴⍳4

So if you can accept John's argument up to the point where he justifies the difference between a simple scalar ref and an array of them it requires no more justification to accept this:
      (,#).{⎕←⍵}'This' 'looks' 'wrong'
This
looks
wrong

and from there the (⊂) distributes a (,#) to each word which as we know is itself distributed to the scalars in the word.
      (⊂,#).{⎕←⍵}'This' 'looks' 'wrong'
T
h
i
s
l
...
User avatar
Phil Last
 
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Thu Apr 14, 2011 4:59 pm

I'm afraid we're nearly 50 years too late to expect a one-item vector not to behave like a scalar except in the presence of another scalar. Sometimes a length error would seem appropriate but it just doesn't happen.


Yes, but the troubling part is that in this case the scalar doesn't behave like a scalar - if that's the case, then the 1-vector definitely should NOT behave like a scalar! :)
Erik.Friis
 
Posts: 66
Joined: Mon Apr 04, 2011 3:16 pm

Re: Improper Behaviour From Arrays of Objects?

Postby JohnS|Dyalog on Fri Apr 15, 2011 6:48 am

Hi Erik. I see your point but I'm going to have to invoke the programmer's favourite excuse: "that's the way the code is structured" :-).

The dot-referencing code diverges depending on whether the item to the left of the dot has depth=0 or not. If not, it calls the single-conformability code, as used by the primitive scalar dyadic functions: + - × ÷ ...

Note that, in Dyalog, single-item arrays of any rank are conformable with non-single arrays, as this was the norm at the time we started implementation.
JohnS|Dyalog
 

Re: Improper Behaviour From Arrays of Objects?

Postby Erik.Friis on Fri Apr 15, 2011 2:46 pm

John,

Since the following has a depth of zero and does not call the single-conformability code:

Code: Select all
     #.{⎕←⍵}'Hello'


(I'm assuming it's special cased, and rightly so) could not:

Code: Select all
     (,#).{⎕←⍵}'Hello'


Also invoke the special case code which treats the function as if it has infinite rank. The fact that these two cases produce wildly differing output can be very confusing and lead to some difficult bugs. Perhaps the existence of the parentheses could determine whether the special case code is invoked or not:

Code: Select all
     #.{⎕←⍵}'Hello'
Hello
     x←,#
     x.{⎕←⍵}'Hello'
Hello
     (#).{⎕←⍵}'Hello'
H
e
l
l
o
     (,#).{⎕←⍵}'Hello'
H
e
l
l
o


Thus preserving the original notation and the way it works and the newer notation and the way it should work.
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