If I can merge this thread with the one I started yesterday...> "If the object does not have a class attribute, it has an implicitclass..."> which I take to mean that if an object does have a class attribute itdoes not also have an implicit class.> I think this is reasonable behavior. Consider the "Date" class, whichstores values as "numeric":> > class(Sys.Date()) > [1] "Date" > > inherits(Sys.Date(),"numeric") > [1] FALSE > > class(unclass(Sys.Date())) > [1] "numeric" > > Sys.Date()%%2 > Error in Ops.Date(Sys.Date(), 2) : %% not defined for "Date" objects > Letting the modulus operator (as one example) inherit the numeric classhere could create problems. I disagree. A date object should probably extend integers rather than numerics, in the first place. However, if it extends numeric, then it extends numeric, otherwise it's a contradiction. So, inherits(Sys.Date(),"numeric") should return true. Modulo operators should be defined for both dates and numerics. However, the application of modulo operators to dates, is perhaps unclear, at least in the general case, anyway.> so instead of hitting utils:::head.function, it hits utils:::head.default > I also see this behavior at least as far aback as 3.5.1, so its not newto 3.5.3. These seem like significant design flaws. Implicit classes or whatever you want to call them, are clearly part of the class hierarchy. They should be included in inherits(), is() and standard method dispatch, regardless of whether they are part of the class vector or not. Also, is this something that was introduced in R 3.5.1? The only thing worse than a design flaw is a design flaw that isn't backward compatible. [[alternative HTML version deleted]]
I think this goes back to SV4 (c. late 1990's). The is.<type> functions are much older (c. mid 1970's) , from before any class system was in S. is() and inherits() were introduced with the S4 class system and were meant to escape from the prison made by ancient design choices. Bill Dunlap TIBCO Software wdunlap tibco.com On Tue, Mar 26, 2019 at 2:11 PM Abs Spurdle <spurdle.a at gmail.com> wrote:> If I can merge this thread with the one I started yesterday... > > > "If the object does not have a class attribute, it has an implicit > class..." > > which I take to mean that if an object does have a class attribute it > does not also have an implicit class. > > I think this is reasonable behavior. Consider the "Date" class, which > stores values as "numeric": > > > class(Sys.Date()) > > [1] "Date" > > > inherits(Sys.Date(),"numeric") > > [1] FALSE > > > class(unclass(Sys.Date())) > > [1] "numeric" > > > Sys.Date()%%2 > > Error in Ops.Date(Sys.Date(), 2) : %% not defined for "Date" objects > > Letting the modulus operator (as one example) inherit the numeric class > here could create problems. > > I disagree. > A date object should probably extend integers rather than numerics, in the > first place. > However, if it extends numeric, then it extends numeric, otherwise it's a > contradiction. > So, inherits(Sys.Date(),"numeric") should return true. > > Modulo operators should be defined for both dates and numerics. > However, the application of modulo operators to dates, is perhaps unclear, > at least in the general case, anyway. > > > so instead of hitting utils:::head.function, it hits utils:::head.default > > I also see this behavior at least as far aback as 3.5.1, so its not new > to 3.5.3. > > These seem like significant design flaws. > Implicit classes or whatever you want to call them, are clearly part of the > class hierarchy. > > They should be included in inherits(), is() and standard method dispatch, > regardless of whether they are part of the class vector or not. > > Also, is this something that was introduced in R 3.5.1? > The only thing worse than a design flaw is a design flaw that isn't > backward compatible. > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
Hi Abs, Lets try to remain civil even when disagreeing about major design philosophies, ok? On Tue, Mar 26, 2019 at 2:08 PM Abs Spurdle <spurdle.a at gmail.com> wrote:> If I can merge this thread with the one I started yesterday... > > > "If the object does not have a class attribute, it has an implicit > class..." > > which I take to mean that if an object does have a class attribute it > does not also have an implicit class. > > I think this is reasonable behavior. Consider the "Date" class, which > stores values as "numeric": > > > class(Sys.Date()) > > [1] "Date" > > > inherits(Sys.Date(),"numeric") > > [1] FALSE > > > class(unclass(Sys.Date())) > > [1] "numeric" > > > Sys.Date()%%2 > > Error in Ops.Date(Sys.Date(), 2) : %% not defined for "Date" objects > > Letting the modulus operator (as one example) inherit the numeric class > here could create problems. > > I disagree. > A date object should probably extend integers rather than numerics, in the > first place. > However, if it extends numeric, then it extends numeric, otherwise it's a > contradiction. > So, inherits(Sys.Date(),"numeric") should return true. >You seem to be approaching the S3 "class"/dispatch system as something that it is not: a formal class system. S3 dispatch is based, essentially, on labeling, via the class attribute (or, if you like, the value returned by class(), this is basically the same with some fiddly bits for S4, judging by a quick glance at src/main/attrib.c:do_class ). If it is not in the set of class labels, S3 dispatch *will not* treat it as that class. This is by design. An S3 object's "class" also has no* bearing on the contents of the object (* this isn't true for some built in atomic vector classes, as I Recall, but it is for all user defined classes).> mylist = list("hi", "what?")> class(mylist) = "Date"> mylist[1] NA NA *Warning messages:* *1: In as.POSIXlt.Date(x) : NAs introduced by coercion* *2: In as.POSIXlt.Date(x) : NAs introduced by coercion* See? the print method looks at the class attribute of mylist, and says "Oh, this is a Date, I'll use print.Date" and then it craps out (with NAs instead of errors, but still) because the data contained within the object isn't really a "Date". But there is no definition of what it means to be an S3 "Date" object anywhere, other than that it has the Date class attribute. All of the above is *by design*. You're welcome to not like the design. I prefer the formalism of S4, myself, and there are various things I don't love about how S3 works - including some but not all of the things that have come up here. That said, the behaviors are not bugs, and any of the changes you seem to be advocating for would not only break lots of code, but would also represent fundamental changes to the design of a core aspect of the R language. As for doing %% on Dates, I seriously doubt anyone who is operating on Date objects and thinking about times and dates is looking to do a modulo operation in number of Days since Jan 1st 1970, which is what that operation would do. Better to have that fail and if that really, for sure is what the user actually wants to do, they can uncalss it or otherwise convert it to a numeridc first.> Modulo operators should be defined for both dates and numerics. > However, the application of modulo operators to dates, is perhaps unclear, > at least in the general case, anyway. > > > so instead of hitting utils:::head.function, it hits > utils:::head.default > > I also see this behavior at least as far aback as 3.5.1, so its not new > to 3.5.3. >> These seem like significant design flaws. > Implicit classes or whatever you want to call them, are clearly part of > the class hierarchy. >I'm not sure what is clear about that, or what class hierarchy you're talking about in the S3 case. Remember that S3 classes *have no formal definitions at all*. Thats why I rarely if ever use them in software that I write. But it's an important point here. What something would becomes if you unclass()ed it has no bearing on what S3 dispatch will do.> > They should be included in inherits(), is() and standard method dispatch, > regardless of whether they are part of the class vector or not. >Dispatch is ONLY done on the class vector for S3 (AFAIK). Only. That is how S3 dispatch is defined and designed.> > Also, is this something that was introduced in R 3.5.1? > The only thing worse than a design flaw is a design flaw that isn't > backward compatible. >No that is just the non-devel R I had handy, and you had seemed to be presenting it as something new in 3.5.3. I would be surprised if the behavior doesn't go all the way back to whenever head.function was added. Before that head() on a function (likely) would have failed just like it still does on your reclassed function. Because, again, this is how S3 is supposed to behave when you give it the inputs you are. I fyou want your f class to hit function S3 methods, you need to do class(myfun) <- c("f", "function") Then everything will work. Best, ~G [[alternative HTML version deleted]]
> you had seemed to be presenting it as something new in 3.5.3. I would besurprised if the behavior doesn't go all the way back to whenever head.function was added. My bad. I'm just surprised I've never noticed these problems before.> S3 classes have no formal definitions at all > I'm not sure what is clear about that, or what class hierarchy you'retalking about in the S3 case. That's questionable. One, because it depends on how you define formal definitions. And two, because class definitions can exist outside the code itself. e.g. As part of an object oriented model. (Being "Object Oriented" is just as much about models as it is about syntax). Furthermore, when you change the class of a vector, list or function, much of the original object's structure and behavior remains. So, it has "Inherited" or "Extended", in my opinion. Resulting in a class hierarchy.> Dispatch is ONLY done on the class vector for S3 (AFAIK)Incorrect. We've already mentioned the example of head.function(). In general, this dispatch occurs without the presence of a class attribute.> You seem to be approaching the S3 "class"/dispatch system as somethingthat it is not: a formal class system If I can diverge... Where did this term "Formal Class System" come from? I've never seen it used anywhere else. Is is specific to R? [[alternative HTML version deleted]]
> the prison made by ancient design choicesThat prison of ancient design choices isn't so bad. I have no further comments on object oriented semantics. However, I'm planning to follow the following design pattern. If I set the class of an object, I will append the new class to the existing class. #good class (object) = c ("something", class (object) ) #bad class (object) = "something" I encourage others to do the same.