UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ Lab 12

Before the lab

A Vector class

Time
25 minutes
Activity
Exercise from book.

Do the Vector Type exercise.

test("addition", (t) =>
    assert.deepStrictEqual(new Vec(1, 2).plus(new Vec(2, 3)),
                           new Vec(3,5)));
test("subtraction", (t)=>
    assert.deepStrictEqual(new Vec(1, 2).minus(new Vec(2, 3)),
                           new Vec(-1,-1)));
test("length", (t) =>
    assert.strictEqual(new Vec(3, 4).length,5));

A Set ("Group") class

Time
30 minutes
Activity
Exercise from book.

Do the Group exercise. Instead of the suggested array, use an object to store the elements of the "Group". The simplest way to implement from is to loop over the iterable argument and repeatedly call add.

const test=require("node:test");
const assert=require("assert");
class Group {
    constructor() {
        this.elements={}
    }
    add(element) {
        this.elements[element]=true;
    }
    has(element) {
    }
    delete(element) {
    }
    static from(iterable) {
    }
}
let group = Group.from([10, 20]);
test("has yes",(t)=>assert.strictEqual(group.has(10),true));
test("has no",(t)=>assert.strictEqual(group.has(30),false));
test("add existing is not error", (t)=>group.add(10));
test("delete existing", (t) => {
    group.delete(10);
    assert.strictEqual(group.has(10),false);
});

Symbols

Time
10 minutes
Activity
Demo

You might remember symbols from Racket. It turns out JavaScript has something similar (but more confusing). Just like strings, Symbols can be used as keys (e.g. method names for objects). Here we rely on a predefined value to be able to call a method. In the last part of the lab, you will use the global Symbol.iterator as a method name.

const test=require("node:test");
const assert=require("assert");

let sym=Symbol("my cool symbol name");

test("uniqueness",
     (t)=>assert.notEqual(sym, Symbol("my cool symbol name")));

class Thing {
    constructor() {
        this.count=0;
    }
    // note the syntax to define indirect method names
    [sym]() {
        return this.count++;
    }
}

test("call",
     (t)=> {
         let x = new Thing();
         assert.strictEqual(x[sym](),0);
         assert.strictEqual(x[sym](),1);
     });

Iterable class

Time
40 minutes
Activity
Exercise from book.

Do the Iterable Group exercise.

Start by adding the following two methods to your Group class.

    // Utility function for iterator class
    keys() {
        return Object.keys(this.elements);
    }
    // Mark this class as iterable.
    [Symbol.iterator]() {
        return new GroupIterator(this);
    }

Next create a GroupIterator class.

class GroupIterator {
    constructor(group) {
        this.index=0;
        this.group=group;
    }
    next() {
    }
}

Refer to the MatrixIterator class for inspiration, but note that you should always return an object with a value property. When you are done, the following test should pass.

test("iterate", (t) => {
    let vals=[];
    for (let value of Group.from(["a", "b", "c"])) {
        vals.push(value+value);
    }
    assert.deepStrictEqual(vals,["aa","bb","cc"]);
});