Improper Behaviour From Arrays of Objects?
12 posts
• Page 1 of 2 • 1, 2
Improper Behaviour From Arrays of Objects?
I defined the following class:
And was interested to see the behaviour of arrays of objects when calling the method Print.
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.
- 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?
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.
-
Phil Last - Posts: 628
- Joined: Thu Jun 18, 2009 6:29 pm
- Location: Wessex
Re: Improper Behaviour From Arrays of Objects?
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 ;)
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?
- 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?
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:
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:
So this is what's happening with Phil's example:
The 1-vector (,#) is conformable with the 5-vector 'Hello' and so the function is distributed and applied five times. Had Phil typed:
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.
[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?
Hi John,
Nice to see you again! I follow your argument until you get to the statement:
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.
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?
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!:
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:
and from there the (⊂) distributes a (,#) to each word which as we know is itself distributed to the scalars in the word.
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
...
-
Phil Last - Posts: 628
- Joined: Thu Jun 18, 2009 6:29 pm
- Location: Wessex
Re: Improper Behaviour From Arrays of Objects?
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?
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.
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?
John,
Since the following has a depth of zero and does not call the single-conformability code:
(I'm assuming it's special cased, and rightly so) could not:
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:
Thus preserving the original notation and the way it works and the newer notation and the way it should work.
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
12 posts
• Page 1 of 2 • 1, 2
Return to Object Oriented Programming
Who is online
Users browsing this forum: No registered users and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group