Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can i spread an Array of parameter names into a function declaration

I have an object which returns,

[
    {
        name:"getSpeed",
        params:["distance","time"]
    },
    {
        name:"getTime",
        params:["speed","distance"]
    },
    ...
]

This object is subject to change as it is gathered from an embedded device.

im trying to convert this into an object with callable functions i.e.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


let myObj = {
    getSpeed: function(distance, time){
        /* do something (this is irrelevant) */
    },
    getTime: function(speed, distance){
        /* do something (again not relevant) */
    }

}

is there any way to map an array of strings to function parameters when mapping over an array?

>Solution :

According to your comments it appears you want to create functions from this definition which send commands with a function-call-like string which is evaled on the other side, and you don’t actually care about the paramater names but rather about the correct number of parameters.

I would therefore recommend something like this:

const myObj = Object.fromEntries(data.map(({ name, params }) => [
  name,
  (...args) => {
    if (args.length !== params.length) {
      throw new TypeError(`${name} expected ${params.length} arguments, got ${args.length}`)
    }
    
    this.UART.write(`${name}(${args.map(arg => JSON.stringify(arg)).join(',')})`)
  }
]))

This will work with all the datatypes that JSON supports, and will as a side effect also pass undefined as argument correctly.

Here is a runnable example with console.log instead of this.UART.write:

const data = [
    {
        name: "getSpeed",
        params: ["distance", "time"]
    },
    {
        name: "getTime",
        params: ["speed", "distance"]
    }
]


const myObj = Object.fromEntries(data.map(({ name, params }) => [
  name,
  (...args) => {
    if (args.length !== params.length) {
      throw new TypeError(`${name} expected ${params.length} arguments, got ${args.length}`)
    }

    console.log(`${name}(${args.map(arg => JSON.stringify(arg)).join(',')})`)
  }
]))

myObj.getSpeed(123, 456) // prints `getSpeed(123,456)`
myObj.getTime(123, 456) // prints `getTime(123,456)`
myObj.getTime("hello", true) // prints `getTime("hello",true)`
myObj.getTime(1) // throws `getTime expected 2 arguments, got 1`

However, as you said yourself, the whole eval business is not ideal anyway. I would recommend – if possible – to reconsider the protocol to use something more secure and robust like gRPC or, one layer below, protocol buffers. Given that you are using JavaScript on both ends, JSON-RPC could also be a nice solution.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading