Skip to content

Commit

Permalink
Add RObject.class() method, tests, and update NEWS.md (#416)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgestagg committed Apr 24, 2024
1 parent 3eef6fc commit 58f4d16
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* A `webR.version` property has been added, containing the current version and build information (#409).

* An `RObject.class()` method has been added, returning an `RCharacter` object with the names of the classes from which the given R object inherits. This has been implemented using R's `class()` function, and so the implicit class is similarly returned when the R object has no `class` attribute.

# webR 0.3.2

## New features
Expand Down
34 changes: 34 additions & 0 deletions src/tests/webR/robj.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,40 @@ test('Get RObject type as a string', async () => {
expect(await result.toString()).toEqual('[object RObject:null]');
});

describe('Working with R object classes', () => {
test('Get R object intrinsic class', async () => {
const numeric = await new webR.RDouble([1, 2, 3]);
const character = await new webR.RCharacter(['a', 'b', 'c']);

const numericClass = await numeric.class();
const characterClass = await character.class();
expect(await numericClass.toArray()).toContain("numeric");
expect(await characterClass.toArray()).toContain("character");
});

test('Get R object class vector', async () => {
const jsObj = { a: [1, 2, 3], b: [3, 4, 5], c: ['x', 'y', 'z'] };
const rObj = await new webR.RDataFrame(jsObj);
const classes = await rObj.class();
expect(await classes.toArray()).toEqual(["data.frame"]);
});

test('Get R object class vector from attributes', async () => {
const rObj = await webR.evalR('x <- 123; class(x) <- c("abc", "def"); x');
const classes = await rObj.class();
expect(await classes.toArray()).toEqual(["abc", "def"]);
});

test('Get S4 R object class vector', async () => {
const rClass = await webR.evalR('getClass("MethodDefinition")');
const classes = await rClass.class();
const attrs = await rClass.attrs();
const attrPackage = await attrs.get('package');
expect(await classes.toArray()).toEqual(["classRepresentation"]);
expect(await attrPackage.toString()).toEqual("methods");
});
});

describe('Working with R lists and vectors', () => {
test('Get R object attributes', async () => {
const vector = await webR.evalR('c(a=1, b=2, c=3)');
Expand Down
11 changes: 11 additions & 0 deletions src/webR/robj-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,17 @@ export class RObject extends RObjectBase {
return RPairlist.wrap(Module._ATTRIB(this.ptr));
}

class(): RCharacter {
const prot = { n: 0 };
const classCall = new RCall([new RSymbol('class'), this]);
protectInc(classCall, prot);
try {
return classCall.eval() as RCharacter;
} finally {
unprotect(prot.n);
}
}

setNames(values: (string | null)[] | null): this {
let namesObj: RObject;

Expand Down

0 comments on commit 58f4d16

Please sign in to comment.