FAQ
List,

In order to get rid of some old, unreadable S3 code in package sp, I'm
trying to rewrite things using S4 methods. Somewhere I fail, and I
cannot sort out why. In order to isolate the problem, I created two
functions, doNothing<- and dosth, and both should do nothing. The issue
is that in most cases they do nothing, but in some cases dosth(obj)
changes the class of obj and breaks with the error. I couldn't find a
pattern when this happens, but have a few cases where it consistently
breaks. Here's the code snippet:

setGeneric("doNothing<-", function(object, value)
standardGeneric("doNothing<-"))

setReplaceMethod("doNothing",
signature(object = "Spatial", value = "ANY"),
function(object, value) object)

dosth = function(obj) {
cl1 = class(obj)
doNothing(obj) = TRUE
cl2 = class(obj)
if (!identical(cl1, cl2)) {
print(paste(cl1, cl2))
stopifnot(identical(cl1, cl2))
}
obj
}

When things go wrong, dosth and doNothing are called with a subclass of
Spatial, e.g. an object of class SpatialGrid, but when this gets in
doNothing, the object is suddenly of class Spatial, and is then returned
as an object of class Spatial, which should never happen.

For instance, I have a case where consistently

setMethod("fullgrid", c("Spatial"),
function(obj) { is(obj, "SpatialGrid") })
class(g)
[1] "SpatialGrid"
attr(,"package")
[1] "sp"
fullgrid(g)
[1] FALSE

is obviously false, but in other cases it works fine.

When I change the signature of doNothing to signature(object = "ANY",
value = "ANY"), the problem disappears.

I tried to make a self-contained example that reproduced the issue, but
could only get something that worked as expected.

I would appreciate any help or suggestions.
--
Edzer Pebesma
Institute for Geoinformatics (ifgi), University of M?nster
Weseler Stra?e 253, 48151 M?nster, Germany. Phone: +49 251
8333081, Fax: +49 251 8339763 http://ifgi.uni-muenster.de
http://www.52north.org/geostatistics e.pebesma at wwu.de

Search Discussions

  • Edzer Pebesma at Sep 18, 2011 at 10:33 am
    As a follow-up, I managed to isolate the problem I sent earlier this
    week, and reduced it to a small case (I'm using R 2.13.1,
    i486-pc-linux-gnu (32-bit)).

    The following script does what I expect:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)

    setAs("AB", "A", function(from) new("A", x = from at x))
    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    and results in class(x) being "AB".
    However, the following, very similar script:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    setAs("AB", "A", function(from) new("A", x = from at x))

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    returns "A" as the class of x. Why is this the case? Is this behaviour
    intentional?

    Best regards,

    On 09/14/2011 11:00 PM, Edzer Pebesma wrote:
    List,

    In order to get rid of some old, unreadable S3 code in package sp, I'm
    trying to rewrite things using S4 methods. Somewhere I fail, and I
    cannot sort out why. In order to isolate the problem, I created two
    functions, doNothing<- and dosth, and both should do nothing. The issue
    is that in most cases they do nothing, but in some cases dosth(obj)
    changes the class of obj and breaks with the error. I couldn't find a
    pattern when this happens, but have a few cases where it consistently
    breaks. Here's the code snippet:

    setGeneric("doNothing<-", function(object, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing",
    signature(object = "Spatial", value = "ANY"),
    function(object, value) object)

    dosth = function(obj) {
    cl1 = class(obj)
    doNothing(obj) = TRUE
    cl2 = class(obj)
    if (!identical(cl1, cl2)) {
    print(paste(cl1, cl2))
    stopifnot(identical(cl1, cl2))
    }
    obj
    }

    When things go wrong, dosth and doNothing are called with a subclass of
    Spatial, e.g. an object of class SpatialGrid, but when this gets in
    doNothing, the object is suddenly of class Spatial, and is then returned
    as an object of class Spatial, which should never happen.

    For instance, I have a case where consistently

    setMethod("fullgrid", c("Spatial"),
    function(obj) { is(obj, "SpatialGrid") })
    class(g)
    [1] "SpatialGrid"
    attr(,"package")
    [1] "sp"
    fullgrid(g)
    [1] FALSE

    is obviously false, but in other cases it works fine.

    When I change the signature of doNothing to signature(object = "ANY",
    value = "ANY"), the problem disappears.

    I tried to make a self-contained example that reproduced the issue, but
    could only get something that worked as expected.

    I would appreciate any help or suggestions.
    --
    Edzer Pebesma
    Institute for Geoinformatics (ifgi), University of M?nster
    Weseler Stra?e 253, 48151 M?nster, Germany. Phone: +49 251
    8333081, Fax: +49 251 8339763 http://ifgi.uni-muenster.de
    http://www.52north.org/geostatistics e.pebesma at wwu.de
  • John Chambers at Sep 18, 2011 at 9:04 pm
    The distinction here is "simple inheritance" ("Software for Data
    Analysis", p. 346). Your first example is simple inheritance (would be
    clearer if you used the contains= argument). In the second version you
    supply an explicit coerce method, so method dispatch can no longer just
    pass in the object from the subclass, but has to call the coerce method
    explicitly. Details in the reference.

    If you need to have an explicit coerce method, it's possible to emulate
    simple inheritance, but the programming may be more subtle than you want
    to take on. When your method is called, it actually gets also an
    argument strict= which will be FALSE for method dispatch. You need to
    take account of the strict= argument in writing your method. See ?setAs
    for a few more details. Someone on the list may have an example.

    John
    On 9/18/11 3:33 AM, Edzer Pebesma wrote:
    As a follow-up, I managed to isolate the problem I sent earlier this
    week, and reduced it to a small case (I'm using R 2.13.1,
    i486-pc-linux-gnu (32-bit)).

    The following script does what I expect:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)

    setAs("AB", "A", function(from) new("A", x = from at x))
    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    and results in class(x) being "AB".
    However, the following, very similar script:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    setAs("AB", "A", function(from) new("A", x = from at x))

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    returns "A" as the class of x. Why is this the case? Is this behaviour
    intentional?

    Best regards,

    On 09/14/2011 11:00 PM, Edzer Pebesma wrote:
    List,

    In order to get rid of some old, unreadable S3 code in package sp, I'm
    trying to rewrite things using S4 methods. Somewhere I fail, and I
    cannot sort out why. In order to isolate the problem, I created two
    functions, doNothing<- and dosth, and both should do nothing. The issue
    is that in most cases they do nothing, but in some cases dosth(obj)
    changes the class of obj and breaks with the error. I couldn't find a
    pattern when this happens, but have a few cases where it consistently
    breaks. Here's the code snippet:

    setGeneric("doNothing<-", function(object, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing",
    signature(object = "Spatial", value = "ANY"),
    function(object, value) object)

    dosth = function(obj) {
    cl1 = class(obj)
    doNothing(obj) = TRUE
    cl2 = class(obj)
    if (!identical(cl1, cl2)) {
    print(paste(cl1, cl2))
    stopifnot(identical(cl1, cl2))
    }
    obj
    }

    When things go wrong, dosth and doNothing are called with a subclass of
    Spatial, e.g. an object of class SpatialGrid, but when this gets in
    doNothing, the object is suddenly of class Spatial, and is then returned
    as an object of class Spatial, which should never happen.

    For instance, I have a case where consistently

    setMethod("fullgrid", c("Spatial"),
    function(obj) { is(obj, "SpatialGrid") })
    class(g)
    [1] "SpatialGrid"
    attr(,"package")
    [1] "sp"
    fullgrid(g)
    [1] FALSE

    is obviously false, but in other cases it works fine.

    When I change the signature of doNothing to signature(object = "ANY",
    value = "ANY"), the problem disappears.

    I tried to make a self-contained example that reproduced the issue, but
    could only get something that worked as expected.

    I would appreciate any help or suggestions.
  • Edzer Pebesma at Sep 30, 2011 at 7:48 am
    Thanks, John!

    I did not manage to figure out how the strict= works, but changed class
    inheritance such that simple inheritance did not take place.

    I see you're advocating to use the contains= to stress inheritance; back
    in 2005, I followed the green book, which did not yet have this.

    If I now would change class definitions from using the representation=
    into contains= to express inheritance, does the binary representation
    also change, i.e. do people relying on sp classes get into problem with
    old, saved objects read by the new software? I'm asking this because
    there's lots of it around, e.g. all the world administrative regions
    available as .RData files from http://gadm.org/ .
    On 09/18/2011 11:04 PM, John Chambers wrote:
    The distinction here is "simple inheritance" ("Software for Data
    Analysis", p. 346). Your first example is simple inheritance (would be
    clearer if you used the contains= argument). In the second version you
    supply an explicit coerce method, so method dispatch can no longer just
    pass in the object from the subclass, but has to call the coerce method
    explicitly. Details in the reference.

    If you need to have an explicit coerce method, it's possible to emulate
    simple inheritance, but the programming may be more subtle than you want
    to take on. When your method is called, it actually gets also an
    argument strict= which will be FALSE for method dispatch. You need to
    take account of the strict= argument in writing your method. See ?setAs
    for a few more details. Someone on the list may have an example.

    John
    On 9/18/11 3:33 AM, Edzer Pebesma wrote:
    As a follow-up, I managed to isolate the problem I sent earlier this
    week, and reduced it to a small case (I'm using R 2.13.1,
    i486-pc-linux-gnu (32-bit)).

    The following script does what I expect:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)

    setAs("AB", "A", function(from) new("A", x = from at x))
    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    and results in class(x) being "AB".
    However, the following, very similar script:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    setAs("AB", "A", function(from) new("A", x = from at x))

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    returns "A" as the class of x. Why is this the case? Is this behaviour
    intentional?

    Best regards,

    On 09/14/2011 11:00 PM, Edzer Pebesma wrote:
    List,

    In order to get rid of some old, unreadable S3 code in package sp, I'm
    trying to rewrite things using S4 methods. Somewhere I fail, and I
    cannot sort out why. In order to isolate the problem, I created two
    functions, doNothing<- and dosth, and both should do nothing. The issue
    is that in most cases they do nothing, but in some cases dosth(obj)
    changes the class of obj and breaks with the error. I couldn't find a
    pattern when this happens, but have a few cases where it consistently
    breaks. Here's the code snippet:

    setGeneric("doNothing<-", function(object, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing",
    signature(object = "Spatial", value = "ANY"),
    function(object, value) object)

    dosth = function(obj) {
    cl1 = class(obj)
    doNothing(obj) = TRUE
    cl2 = class(obj)
    if (!identical(cl1, cl2)) {
    print(paste(cl1, cl2))
    stopifnot(identical(cl1, cl2))
    }
    obj
    }

    When things go wrong, dosth and doNothing are called with a subclass of
    Spatial, e.g. an object of class SpatialGrid, but when this gets in
    doNothing, the object is suddenly of class Spatial, and is then returned
    as an object of class Spatial, which should never happen.

    For instance, I have a case where consistently

    setMethod("fullgrid", c("Spatial"),
    function(obj) { is(obj, "SpatialGrid") })
    class(g)
    [1] "SpatialGrid"
    attr(,"package")
    [1] "sp"
    fullgrid(g)
    [1] FALSE

    is obviously false, but in other cases it works fine.

    When I change the signature of doNothing to signature(object = "ANY",
    value = "ANY"), the problem disappears.

    I tried to make a self-contained example that reproduced the issue, but
    could only get something that worked as expected.

    I would appreciate any help or suggestions.
    --
    Edzer Pebesma
    Institute for Geoinformatics (ifgi), University of M?nster
    Weseler Stra?e 253, 48151 M?nster, Germany. Phone: +49 251
    8333081, Fax: +49 251 8339763 http://ifgi.uni-muenster.de
    http://www.52north.org/geostatistics e.pebesma at wwu.de
  • John Chambers at Sep 30, 2011 at 4:16 pm

    On 9/30/11 12:48 AM, Edzer Pebesma wrote:
    Thanks, John!

    I did not manage to figure out how the strict= works, but changed class
    inheritance such that simple inheritance did not take place.

    I see you're advocating to use the contains= to stress inheritance; back
    in 2005, I followed the green book, which did not yet have this.

    If I now would change class definitions from using the representation=
    into contains= to express inheritance, does the binary representation
    also change, i.e. do people relying on sp classes get into problem with
    old, saved objects read by the new software? I'm asking this because
    there's lots of it around, e.g. all the world administrative regions
    available as .RData files from http://gadm.org/
    It's just a question of readability: Better to have a clear statement of
    inheritance rather than plowing through the representation list for
    empty name fields. And easier to discuss (e.g., section 9.3 of SoDA).

    You're hardly the only sinner in the flock. I imagine many packages on
    CRAN would have failed by now if there was a problem. I only complain
    about it when feeling fussy.

    John
    .
    On 09/18/2011 11:04 PM, John Chambers wrote:
    The distinction here is "simple inheritance" ("Software for Data
    Analysis", p. 346). Your first example is simple inheritance (would be
    clearer if you used the contains= argument). In the second version you
    supply an explicit coerce method, so method dispatch can no longer just
    pass in the object from the subclass, but has to call the coerce method
    explicitly. Details in the reference.

    If you need to have an explicit coerce method, it's possible to emulate
    simple inheritance, but the programming may be more subtle than you want
    to take on. When your method is called, it actually gets also an
    argument strict= which will be FALSE for method dispatch. You need to
    take account of the strict= argument in writing your method. See ?setAs
    for a few more details. Someone on the list may have an example.

    John
    On 9/18/11 3:33 AM, Edzer Pebesma wrote:
    As a follow-up, I managed to isolate the problem I sent earlier this
    week, and reduced it to a small case (I'm using R 2.13.1,
    i486-pc-linux-gnu (32-bit)).

    The following script does what I expect:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)

    setAs("AB", "A", function(from) new("A", x = from at x))
    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    and results in class(x) being "AB".
    However, the following, very similar script:


    setClass("A", representation(x = "numeric"))
    setClass("AB", representation("A"))

    setGeneric("doNothing<-", function(obj, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing", c("A", "character"),
    function(obj, value) obj)

    setAs("AB", "A", function(from) new("A", x = from at x))

    x = new("AB", x = 10)
    doNothing(x) = "irrelevant"
    class(x)


    returns "A" as the class of x. Why is this the case? Is this behaviour
    intentional?

    Best regards,

    On 09/14/2011 11:00 PM, Edzer Pebesma wrote:
    List,

    In order to get rid of some old, unreadable S3 code in package sp, I'm
    trying to rewrite things using S4 methods. Somewhere I fail, and I
    cannot sort out why. In order to isolate the problem, I created two
    functions, doNothing<- and dosth, and both should do nothing. The issue
    is that in most cases they do nothing, but in some cases dosth(obj)
    changes the class of obj and breaks with the error. I couldn't find a
    pattern when this happens, but have a few cases where it consistently
    breaks. Here's the code snippet:

    setGeneric("doNothing<-", function(object, value)
    standardGeneric("doNothing<-"))

    setReplaceMethod("doNothing",
    signature(object = "Spatial", value = "ANY"),
    function(object, value) object)

    dosth = function(obj) {
    cl1 = class(obj)
    doNothing(obj) = TRUE
    cl2 = class(obj)
    if (!identical(cl1, cl2)) {
    print(paste(cl1, cl2))
    stopifnot(identical(cl1, cl2))
    }
    obj
    }

    When things go wrong, dosth and doNothing are called with a subclass of
    Spatial, e.g. an object of class SpatialGrid, but when this gets in
    doNothing, the object is suddenly of class Spatial, and is then
    returned
    as an object of class Spatial, which should never happen.

    For instance, I have a case where consistently

    setMethod("fullgrid", c("Spatial"),
    function(obj) { is(obj, "SpatialGrid") })
    class(g)
    [1] "SpatialGrid"
    attr(,"package")
    [1] "sp"
    fullgrid(g)
    [1] FALSE

    is obviously false, but in other cases it works fine.

    When I change the signature of doNothing to signature(object = "ANY",
    value = "ANY"), the problem disappears.

    I tried to make a self-contained example that reproduced the issue, but
    could only get something that worked as expected.

    I would appreciate any help or suggestions.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupr-devel @
categoriesr
postedSep 14, '11 at 9:00p
activeSep 30, '11 at 4:16p
posts5
users2
websiter-project.org
irc#r

2 users in discussion

Edzer Pebesma: 3 posts John Chambers: 2 posts

People

Translate

site design / logo © 2022 Grokbase