Re: [Rd] head.matrix can return 1000s of columns -- limit to n or add new argument?

2019-11-02 Thread Gabriel Becker
Thanks Martin and Peter,

I agree that we can be careful and narrow and still see a nice improvement
in behavior. While Herve's point is valid and I understand his frustration,
I think staying within the matrix vs  c(matrix, array) space is the right
scope for this work in terms of fiddling with inheritance.

As another point,  I don't know off the top of my head of any other classes
which we would expect to have a dimensions attribute other than arrays
(including the "non-array" 2d matrices) and data.frames, but I imagine
there are some out there.

Do we want the default head and tail methods to be dimension aware as well,
via something along the lines of what I had in my previous message, or do
we want to retain the old behavior for things that aren't data.frames or
matrix/arrays? If the dim attribute can always be assumed to mean the same
thing I feel like it would be nice to give the dimensionality awareness
(and idempotence) to anything with dimensions, but again I don't know much
about the other classes taht have that attribute or how people want to use
them.

It would of course be written in a way that still worked identically to now
for any object that does not have a dimension attribute.

Thoughts?

~G

On Fri, Nov 1, 2019 at 1:52 AM Martin Maechler 
wrote:

> > peter dalgaard
> > on Thu, 31 Oct 2019 23:04:29 +0100 writes:
>
> > Hmm, the problem I see here is that these implied classes are all
> inherently one-off. We also have
> >> inherits(matrix(1,1,1),"numeric")
> > [1] FALSE
> >> is.numeric(matrix(1,1,1))
> > [1] TRUE
> >> inherits(1L,"numeric")
> > [1] FALSE
> >> is.numeric(1L)
> > [1] TRUE
>
> > and if we start fixing one, we might need to fix all.
>
> I disagree about "fixing all" (see also my reply to Hervé), and
> the {"numeric","double","integer"} case is particularly messy,
> and I don't want to open that can now.
>
> > For method dispatch, we do have inheritance, e.g.
>
> >> foo.numeric <- function(x) x + 1
> >> foo <- function(x) UseMethod("foo")
> >> foo(1)
> > [1] 2
> >> foo(1L)
> > [1] 2
> >> foo(matrix(1,1,1))
> > [,1]
> > [1,]2
> >> foo.integer <- function(x) x + 2
> >> foo(1)
> > [1] 2
> >> foo(1L)
> > [1] 3
> >> foo(matrix(1,1,1))
> > [,1]
> > [1,]2
> >> foo(matrix(1L,1,1))
> > [,1]
> > [1,]3
>
> > but these are not all automatic: "integer" implies "numeric", but
> "matrix" does not imply "numeric", much less "integer".
>
> well it should not imply in general:
> Contrary to Math,  we also have 'raw' or 'character' or 'logical' matrices.
>
>
> > Also, we seem to have a rule that inherits(x, c)  iff  c %in%
> class(x),
>
> good point, and that's why my usage of  inherits(.,.) was not
> quite to the point.  [OTOH, it was to the point, as indeed from
>   the ?class / ?inherits docu, S3 method dispatch and inherits
>   must be consistent ]
>
> > which would break -- unless we change class(x) to return the whole
> set of inherited classes, which I sense that we'd rather not do
>
> and we have something like that already with  is(.)
>
> Thank you for these important points raised!
>
> Note again that both "matrix" and "array" are special [see ?class] as
> being of  __implicit class__  and I am considering that this
> implicit class behavior for these two should be slightly changed
> such that
>
>   foo <- function(x,...) UseMethod("foo")
>   foo.array <- function(x, ...)
>sprintf("array of dim. %s", paste(dim(x), collapse = " x "))
>
> should work for all arrays and not be an exception for 2D arrays :
>
> > foo(array(pi, 1:3))
> [1] "array of dim. 1 x 2 x 3"
> > foo(array(pi, 1))
> [1] "array of dim. 1"
> > foo(array(pi, 2:7))
> [1] "array of dim. 2 x 3 x 4 x 5 x 6 x 7"
> > foo(array(pi, 1:2))
> Error in UseMethod("foo") :
>   no applicable method for 'foo' applied to an object of class
> "c('matrix', 'double', 'numeric')"
> >
>
> And indeed I think you are right on spot and this would mean
> that indeed the implicit class
> "matrix" should rather become c("matrix", "array").
>
> BTW: The 'Details' section of   ?class   nicely defines things,
>  notably the __implicit class__ situation
>  (but I think should be improved)  :
>
>  {numbering the paragraphs for reference}
>
> > Details:
> >
> > 1.   Here, we describe the so called “S3” classes (and methods). For
> >  “S4” classes (and methods), see ‘Formal classes’ below.
> >
> > 2.   Many R objects have a class attribute, a character vector giving
> >  the names of the classes from which the object _inherits_.
> >  (Functions oldClass and oldClass<- get and set the attribute,
> >  which can also be done directly.)
> >
> > 3.   If the object does not have a class attribute, it has an implicit
> >  class, notably ‘"matrix"’, ‘"array"’, ‘"function"’ or ‘"numeric"’
> >  or the result of ‘typeof(x)’ (which is similar to ‘mod

Re: [Rd] head.matrix can return 1000s of columns -- limit to n or add new argument?

2019-11-02 Thread Gabriel Becker
As I hit send I realized I did know of one, which is table objects. So
while we're discussing it we can talk about both generally and specifically
what head.table and tail.table should do. Looks like tail.table is already
special -cased to hit the matrix method if it is 2d, so the natural
extension of that would be hitting tail.array for any 2+d table, I think.

~G

On Sat, Nov 2, 2019 at 12:37 PM Gabriel Becker 
wrote:

> Thanks Martin and Peter,
>
> I agree that we can be careful and narrow and still see a nice improvement
> in behavior. While Herve's point is valid and I understand his frustration,
> I think staying within the matrix vs  c(matrix, array) space is the right
> scope for this work in terms of fiddling with inheritance.
>
> As another point,  I don't know off the top of my head of any other
> classes which we would expect to have a dimensions attribute other than
> arrays (including the "non-array" 2d matrices) and data.frames, but I
> imagine there are some out there.
>
> Do we want the default head and tail methods to be dimension aware as
> well, via something along the lines of what I had in my previous message,
> or do we want to retain the old behavior for things that aren't data.frames
> or matrix/arrays? If the dim attribute can always be assumed to mean the
> same thing I feel like it would be nice to give the dimensionality
> awareness (and idempotence) to anything with dimensions, but again I don't
> know much about the other classes taht have that attribute or how people
> want to use them.
>
> It would of course be written in a way that still worked identically to
> now for any object that does not have a dimension attribute.
>
> Thoughts?
>
> ~G
>
> On Fri, Nov 1, 2019 at 1:52 AM Martin Maechler 
> wrote:
>
>> > peter dalgaard
>> > on Thu, 31 Oct 2019 23:04:29 +0100 writes:
>>
>> > Hmm, the problem I see here is that these implied classes are all
>> inherently one-off. We also have
>> >> inherits(matrix(1,1,1),"numeric")
>> > [1] FALSE
>> >> is.numeric(matrix(1,1,1))
>> > [1] TRUE
>> >> inherits(1L,"numeric")
>> > [1] FALSE
>> >> is.numeric(1L)
>> > [1] TRUE
>>
>> > and if we start fixing one, we might need to fix all.
>>
>> I disagree about "fixing all" (see also my reply to Hervé), and
>> the {"numeric","double","integer"} case is particularly messy,
>> and I don't want to open that can now.
>>
>> > For method dispatch, we do have inheritance, e.g.
>>
>> >> foo.numeric <- function(x) x + 1
>> >> foo <- function(x) UseMethod("foo")
>> >> foo(1)
>> > [1] 2
>> >> foo(1L)
>> > [1] 2
>> >> foo(matrix(1,1,1))
>> > [,1]
>> > [1,]2
>> >> foo.integer <- function(x) x + 2
>> >> foo(1)
>> > [1] 2
>> >> foo(1L)
>> > [1] 3
>> >> foo(matrix(1,1,1))
>> > [,1]
>> > [1,]2
>> >> foo(matrix(1L,1,1))
>> > [,1]
>> > [1,]3
>>
>> > but these are not all automatic: "integer" implies "numeric", but
>> "matrix" does not imply "numeric", much less "integer".
>>
>> well it should not imply in general:
>> Contrary to Math,  we also have 'raw' or 'character' or 'logical'
>> matrices.
>>
>>
>> > Also, we seem to have a rule that inherits(x, c)  iff  c %in%
>> class(x),
>>
>> good point, and that's why my usage of  inherits(.,.) was not
>> quite to the point.  [OTOH, it was to the point, as indeed from
>>   the ?class / ?inherits docu, S3 method dispatch and inherits
>>   must be consistent ]
>>
>> > which would break -- unless we change class(x) to return the whole
>> set of inherited classes, which I sense that we'd rather not do
>>
>> and we have something like that already with  is(.)
>>
>> Thank you for these important points raised!
>>
>> Note again that both "matrix" and "array" are special [see ?class] as
>> being of  __implicit class__  and I am considering that this
>> implicit class behavior for these two should be slightly changed
>> such that
>>
>>   foo <- function(x,...) UseMethod("foo")
>>   foo.array <- function(x, ...)
>>sprintf("array of dim. %s", paste(dim(x), collapse = " x "))
>>
>> should work for all arrays and not be an exception for 2D arrays :
>>
>> > foo(array(pi, 1:3))
>> [1] "array of dim. 1 x 2 x 3"
>> > foo(array(pi, 1))
>> [1] "array of dim. 1"
>> > foo(array(pi, 2:7))
>> [1] "array of dim. 2 x 3 x 4 x 5 x 6 x 7"
>> > foo(array(pi, 1:2))
>> Error in UseMethod("foo") :
>>   no applicable method for 'foo' applied to an object of class
>> "c('matrix', 'double', 'numeric')"
>> >
>>
>> And indeed I think you are right on spot and this would mean
>> that indeed the implicit class
>> "matrix" should rather become c("matrix", "array").
>>
>> BTW: The 'Details' section of   ?class   nicely defines things,
>>  notably the __implicit class__ situation
>>  (but I think should be improved)  :
>>
>>  {numbering the paragraphs for reference}
>>
>> > Details:
>> >
>> > 1.   Here, we describe the s