Marking
- This assignment will be worth 5% of your final grade.
- You will be marked on the last version pushed to coursegit. Make sure you have pushed your assignment by 4:30PM on Thursday October 24.
You will be marked on
- correctness and implementation detail: Pay attention to the way you are asked to implement things.
- functional JavaScript: Part of the point of the assignment is to see that a certain tasks can be accomplished in a very similar way in JavaScript as in Racket. So don’t go crazy with mutation.
- testing: Remember to have full test coverage (according to
node --experimental-test-coverage
).
For detailed marking scheme, see javascript-assignment.
Background
- This assignment is mainly based on Chapters 3-5 of Eloquent JavaScript.
- We also make extensive use of const; it turns out this is not enough to prevent modifying objects. For more details see MDN
- You will need to add the following lines to the top of your file to enable the test framework:
const test=require("node:test");
const assert=require("assert");
What to hand in, and how to hand it in
- Make a directory
~/cs2613/assigments/A3
(i.e. in your git repo for this class). All files related to this assignment should be saved in that directory. - Make sure you commit and push all your work using coursegit by the due date.
expression
function
Conceptually expression
is like one of the make-thing
functions
defined for Racket structs. It takes an ordered list of parameters,
and returns an object allowing access to those same values by
name. You can also think of it as a constructor, although we will
see that constructors in JavaScript typically do more.
Your expression
function should pass the following tests; you will
need to need to write an appropriate function Plus
(more about this below).
const one = expression(Plus,0,1);
test("not null", (t) => assert.notStrictEqual(one,null));
test("not undefined", (t) => assert.notStrictEqual(one,undefined));
test("op", (t) => assert.strictEqual(one.op, Plus));
test("left", (t) => assert.strictEqual(one.left,0));
test("right", (t) => assert.strictEqual(one.right,1));
test('object',
(t)=>assert.deepStrictEqual(expression(Plus,6,7),
{op: Plus, left: 6, right: 7}));
eval
function
The eval
function returns the number equivalent to the given object
without modifying the input object. Your eval
function should pass
the following tests, and use recursion to do the actual evaluation.
You will need to define appropriate Times
, Minus
, Divide
functions.
const six_plus_nine = expression(Plus, 6, 9);
const six_times_nine = expression(Times, 6, 9);
const six_minus_nine = expression(Minus, 6, 9);
const sixteen_div_eight = expression(Divide, 16, 8);
test("+", () => assert.strictEqual(eval(six_plus_nine),15));
test("-", () => assert.strictEqual(eval(six_minus_nine),-3));
test("*", () => assert.strictEqual(eval(six_times_nine),54));
test("/", () => assert.strictEqual(eval(sixteen_div_eight),2));
const compound1 = expression(Plus, six_times_nine, six_plus_nine)
const compound2 = expression(Times, six_times_nine, compound1)
const compound3 = expression(Plus, compound2, 3)
test("compound1", (t) => assert.strictEqual(eval(compound1),69));
test("compound2", (t) => assert.strictEqual(eval(compound2),3726));
test("compound3", () => assert.strictEqual(eval(compound3),3729));
clone_expression
function
Write a function clone_expression
to do a deep copy of an object
created by expression
. Use recursion, not a library function.
Your clone_expression
function should pass the following tests
test("structural equality", function(t) {
const copy3=clone_expression(compound3);
assert.deepStrictEqual(compound3,copy3);
});
test("independence",
function(t) {
const copy4=clone_expression(compound2);
copy4.op=Minus;
assert.notDeepStrictEqual(compound2,copy4);
});
test("immutability", function(t) {
const copy5=clone_expression(compound3);
const val = eval(compound3);
assert.deepStrictEqual(compound3,copy5);
})
test("deep copy", function(t) {
const copy6=clone_expression(compound3);
let copy7=clone_expression(copy6);
copy7.left.left=1;
assert.notDeepStrictEqual(copy6,copy7);
});