简体   繁体   中英

How do I refer to arguments of a function when the function is passed in as a parameter?

New to JavaScript, so give me some leeway.

I'm currently trying to simulate contracts in JavaScript. There are preconditions and postconditions which can be defined when you declare a function. I've compiled a simple setup of how it should work below.

Function mult() has a few contracts which should check if the two inputs are numbers and should check if the resulting output is also a number.

//CONTRACT
function isNumber(v) {
  return !Number.isNaN(v) && typeof v === 'number';
}
isNumber.expected = "number";

/**
 * @param preList Array of contracts to check
 * @param post Expected result type as a contract
 * @param f the function
 */
function contract (preList, post, f) {
    //??? No idea
    //precondition
    for (let i = 0; i < preList.length; i++) {  //THIS DOESNT WORK
        let valid = preList[i].call(this, f.arguments[i]);
        if (valid === false) throw "caller's fault";
    }
    //postcondition
    let result = f.call(this, f.arguments);
    if ((post.call(this, result)) === false) throw "library's fault";
}

//EXAMPLE

var mult = contract(
  [isNumber, isNumber],
  isNumber,
  function mult (x, y) {
    return x*y;
  });

//TEST CODE

console.log("First test")
console.log(mult(3, 4));
console.log();

console.log("Second test")
try {
  console.log(mult(3, "four"));
} catch (e) {
  console.log(e.message);
}
console.log();

I'm fairly sure a lot of the contract(){} function is wrong and after a lot of trial and error I have ended up here.

Currently I'm trying to loop through all the preconditions and call them with the arguments of f. From my understanding, (arguments) refers to the arguments of the current function, but I'm looking for the arguments of f, not of contract. f.arguments

I've also tried to do this with JavaScript proxies which can intercept function calls by setting traps for apply and construct but have gotten stuck as well.

Any help and pointers would be greatly appreciated. Using node.js to run this program.

You can try something like this:

 "use strict"; function isNumber(v) { return !Number.isNaN(v) && typeof v === "number"; } /** * @param preList Array of contracts to check * @param post Expected result type as a contract * @param f the function * @param array: arguments passed to function f */ function contract(preList, post, f, args) { for (let i = 0; i < preList.length; i++) { let valid = preList[i].call(this, args[i]); if (valid === false) throw "caller's fault"; } let result = f.apply(this, args); if (post.call(this, result) === false) throw "library's fault"; return result; } let mult = function(x, y) { let f = function(x, y) { return x * y; }; return contract([isNumber, isNumber], isNumber, f, arguments); }; console.log("First test"); console.log(mult(3, 4)); // 12 console.log("Second test"); try { console.log(mult(3, "four")); } catch (e) { console.log(e); // caller's fault } 

Now that the due date has passed, here's my solution. I wasn't supposed to be returning a value directly, but a function which would return a value after checking the input parameters and the output.

function contract (preList, post, f) {
    return function() {
        for (let i = 0; i < preList.length; i++) {
            let valid = preList[i].call(this, arguments[i]);
            if (!valid)
                throw new Error("Contract violation in position " + i + ". Expected " + preList[i].expected + " but received " + arguments[i] + ".  Blame -> Top-level code");
        }

        let result = f.apply(this, arguments);
        if (!post(result))
            throw new Error("Contract violation. Expected " + post.expected + " but returned " + result + ".  Blame -> " + f.name);

        return result;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM