(Using R 3.5.3). I found bugs in head() and tail(). The following works:> f = function () 1 > head (f)1 function () 2 1 However, the following does not:> class (f) = "f" > head (f)Error in x[seq_len(n)] : object of type 'closure' is not subsettable [[alternative HTML version deleted]]
Hi Abs, This is because the class is "f", not c("f", "function") in your second example. S3 method dispatch is doing what you (unintentionally, I presume) asked it to do. The S3 method which allows head to take functions is utils:::head.function. S3 can only be expected to understand inheritance if the value of class(f) is multivalued. It doesn't have any way of knowing f is still a function after the class assignment because "function" does not appear anywhere in the class vector, so instead of hitting utils:::head.function, it hits utils:::head.default, which uses [ on the argument, causing the error. I'd say this is "expected" behavior within the context of the S3 system. I also see this behavior at least as far aback as 3.5.1, so its not new to 3.5.3. Best, ~G On Mon, Mar 25, 2019 at 8:44 PM Abs Spurdle <spurdle.a at gmail.com> wrote:> (Using R 3.5.3). > > I found bugs in head() and tail(). > > The following works: > > > f = function () 1 > > head (f) > 1 function () > 2 1 > > However, the following does not: > > > class (f) = "f" > > head (f) > Error in x[seq_len(n)] : object of type 'closure' is not subsettable > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
> so instead of hitting utils:::head.function, it hitsutils:::head.default, which uses [ on the argument, causing the error. I've thought about this some more. And I still think that this is a bug. If a generic has a default method, then that default method should be guaranteed to work. Or at least, provide a useful error message, that makes it obvious to the user, what he or she has done wrong. In the case of head.default(), it assumes that the object is a vector, or something similar. This assumption is untrue.>> Error in x[seq_len(n)] : object of type 'closure' is not subsettableResulting in the error above, which fails to recognize that the input was unsuitable. [[alternative HTML version deleted]]
On Wed, Mar 27, 2019 at 1:52 AM Abs Spurdle <spurdle.a at gmail.com> wrote:> > In the case of head.default(), it assumes that the object is a vector, or > something similar. >No it doesn't. It assumes (ultimately) that x[seq_len(n)] is the correct way to generate a "head" of something. Which is reasonable. That's dependent on the implementation of the `[` method on object `x`.> Resulting in the error above, which fails to recognize that the input was > unsuitable. > > Because the object you fed it didn't have a method for `head` or for `[`.Its the object designer's responsibility to do that. And by creating a function that doesn't have the "function" class - that means *you*. There's no way that head.default can inspect everything it might get fed, including classes that have yet to be made, to see if it can do anything meaningful with it. So it uses what looks like a reasonable approach - apply `[` on the object with the first `n` elements. Let the class decide what to do with it. You might think generics should trap errors and give meaningful errors, but the error isn't in the generic here - its in the `[` method of the class it was fed. `head` doesn't know or care about that - again, its the class designers responsibility to handle that, and the users responsibility to *not* call generics on objects for which there's no meaningful behaviour. It's really the error message of `[.default` seeming obscure to you that is your issue here. If it said "cannot create subsets of this object with [" would that please you? Again, that's not a bug in `head` or anything to do with method dispatch. So lets take a look at your choices here: "If a generic has a default method, then that default method should be guaranteed to work." - as demonstrated, the default here does its job. it does "work". "Or at least, provide a useful error message, that makes it obvious to the user, what he or she has done wrong." and that error message is the responsibility of methods of the object, in this case `[`. therefore its not a bug. Barry> [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]