I am a JS dev and to implement this function header,I do :
function gridTraveler(m,n,memo={})
Here,I know that the object would be passed by reference in JS.
So in C++,I decided to do:
int gridTraveler(int m,int n,std::unordered_map<int,int>& memo = {})
But I get an error : "initial reference to a non const must be an lvalue".
How should I pass the default parameter to the function as well as pass the hasmap by reference?
NOTE:I would be editing the memo object by adding in keys and value in the function body
What you meant can probably be achieved by a two-arg overload that takes care of the unordered map lifetime.
int gridTraveler(int m,int n,std::unordered_map<int,int>& memo) {
//your implementation here
}
int gridTraveler(int m, int n) {
std::unordered_map<int,int> memo = {};
return gridTraveler(m, n, memo);
}
Consider explicitly telling it what you really want or creating multiple functions- one that takes a map or one that doesn't.
Possibility 1: You want to sometimes provide a map, but the map serves no operational value; it's just some optional output. C++ does its best to prevent NULL values as references so use a pointer. Adding values to a throwaway map would also be silly if you didn't really need to.
int gridTraveler(int m,int n,std::unordered_map<int,int>* const memo = nullptr)
{
//code stuff for operation
if(memo) //optional output related operations occur if it was provided
{
//populate memo if it is available
}
}
Possibility 2: You want to sometimes output a map that is internally used in operations. When it is not provided, you want to use an empty map as the value and throw it away after. You need a map for your operation but it's a byproduct and you only sometimes care about its values.
int gridTraveler(int m,int n,std::unordered_map<int,int>& memo)
{
//do your thing...
}
int gridTraveler(int m,int n)
{
std::unordered_map<int,int> memo;
const int returnval = gridTraveler(m,n,memo);
//last chance to do something with memo here before it gets thrown out
return returnval;
}
There are a lot of other possibilities- I can think of scenarios where the map would be best implemented class member with gridTraveler being a function of the class and where the map would be in a global scope, only initialized once to empty map per process.
You can not make a reference on a tempory value.
Here: std::unordered_map<int, int>& memo = {} //The "{}" is a tempory value
Use const std::unordered_map<int, int>& memo = {} or use a value without the "&".
Related
Am trying to understand Maps objects in javascript, and how to use them inside an application, but there's something that i cant understand and it leads me to this question, here's my example
const myMap = new Map();
myMap.set('Name', 'John Doe')
.set(1, function sayHello(user){ console.log(`Hello ${user}`)})
myMap.get('Name'); // output John Doe
myMap.get(1); // output [function: sayHello]
as you see above i can set a function inside the Map
how can i use that function?
what's the point of setting a function in a Map?
are there any use cases?
I'm so confused, i will appreciate any explanation
What you've stored in the map is a function object. To understand it better, take a look at the following snippet to observe the difference between sayHello and sayHello("World"). The former is the function object and the latter is an invocation.
const sayHello = (user) => console.log(`Hello ${user}`)
console.log(sayHello);
sayHello("World");
You'd observe that the .get returns you the function object. To see it in action, you need to invoke it with ().
myMap.get(1)("World");
Among other things, maps could help you organize function objects and have, arguably, more readable code. For comparison, check the following implementations.
function calculator(operation, a, b) {
if (operation === "add") {
return a + b;
} else if (operation === "subtract") {
return a - b;
} else if (operation === "multiply") {
return a * b;
}
}
console.log(calculator("add", 5, 10));
console.log(calculator("subtract", 5, 10));
console.log(calculator("multiply", 5, 10));
function calculator(operation, a, b) {
const operations = new Map([
["add", (a, b) => a + b],
["subtract", (a, b) => a - b],
["multiply", (a, b) => a * b],
]);
return operations.get(operation)(a, b);
}
console.log(calculator("add", 5, 10));
console.log(calculator("subtract", 5, 10));
console.log(calculator("multiply", 5, 10));
1. `myMap.get(1)(userName)
2. Several: Functions are objects that define behaviours. You can pass them as parameters as callbacks, transformation filters, etc... Storing them in a Map or just a regular object is just a matter of getting faster access when accessing by some key.
3. Lots of them. You can store not only functions in maps but even whole classes if you want even in most cases it would be more handy (and almost equally efficient) to just use a regular object.
The point is never finding use cases for a thing but having that thing in your toolbox in order to be able to use it as soon as the necessity arises. In this case, when you have a set of key-function pairs big enough.
HINT: If you are curios on more use cases, search for functional programming stuff.
You need to invoke the function by passing the argument like:
myMap.get(1)("user");
If you want to use the function inside the map ( like set above ) then use like this : myMap.get(1)('name')
Map accepts any key type
If the object's key is not a string or symbol, JavaScript implicitly transforms it into a string.
Contrary, the map accepts keys of any type: strings, numbers, boolean, symbols. Moreover, the map preserves the key type. That's the map's main benefit.
There are specific usecases where map win the race over objects :
Map can contain keys of any data type, it could be Objects, integers, strings, boolean, functions or arrays. But in Objects, the key must always be a string or a symbol.
A Map is ordered and iterable, whereas a objects is not ordered and not iterable
Checking the number of entries in a Map is quite easy compared to checking that of Objects.
A Map inherits from Map.prototype. This offers all sorts of utility functions and properties which makes working with Map objects a lot easier
There are chances of accidentally overwriting inherited properties from prototypes by writing JavaScript identifiers as key names of an object (e.g., toString, constructor, etc.) at that case, use Maps
Another object cannot be used as key of an object, so no extra information can be written for an object by writing that object as key of another object and value of that another object will contain the extra information but this is possible in the case of Maps
and much more...
Remember! : debugging with Maps is painful then the objects
I Hope this answer helps you!
Comment if you have any questions or doubts and don't forget to mark the answer as accepted if you find it useful because it'll be helpful for others who're looking the answer for the same question.
Have a great day!
let ar = [];
let p = new Proxy(new Map(), {
get: (o, k) => {
ar.push(1)
return Reflect.get(o, k).bind(o)
},
set: (o, k, v) => {
ar.push(2)
return Reflect.set(o, k, v)
}
});
p.set(1, 2)
p.get(1)
console.log(ar) //Outputs [1,1]
I am trying to intercept both set and get operations on a Map object. I am in no way trying to extend/subclass a Map.
In the process of proxying said Map object, I came across this weird unexpected behavior, the set trap isn't being fired in the above code, but instead the get trap gets fired twice!
I further proceeded to log the k(key) values from the get trap in the following way;
//same code above
get: (o, k) => {
console.log(k) //Logs set and then get!
return Reflect.get(o, k).bind(o)
}
//same code below
The behavior I expect is for the array to be [2,1] and console.log(k) at the get trap to actually output the value of the key.
I wish to know why this happens as so, I've gone through a couple problems like this in here related to proxyifying maps, none of them lead to any sensible reasoning as to why this is happening.
My end goal is to fire an event at the set trap. Am I using Proxy for something it is meant to be used? If not, what approach should I take? Should I abandon using a Map to an Object Literal even though it will bring all the cons of using one? ex: no length property, string-only properties, no forced-unique keys etc.
UPDATE: The more and more I dig into this proxified Map, the more issues I keep coming across. It now seems to me as if the ES6 Proxy API treats Maps the same way as it does an ordinary object. The answer by Vill and my digging backs this up. Why do I say this? Read the following;
//same code above
get: (o, k) => {
if(k === 'tray') return ']'
return Reflect.get(o, k).bind(o)
}
//same code below
p.tray //returns ]
The above code shouldn't theoretically succeed, right? It is as if Proxy is using the same logic to intercept object operations when intercepting Maps as well! As;
///--While the following---//
let m = new Map();
m.set('tray', ']')
m.tray //undefined
Vill's answer says that the Proxy identifies Map.prototype.set as first reading set and invoking it as a function next.
Doesn't that mean in the set trap I've written in the original code(on the very top) doesn't intercept the modification/setting a property of the Map and in fact the implicit/native to Map-Map.prototype.set is used instead of the Reflect.set which we grant through the Proxy?
Doesn't all this further enforce the fact that Proxy and Maps don't mix together well? Am I heading down the wrong way? What am I misunderstanding if so? Are Proxies supposed to treat Maps like just any other object?
It is not bug it is feature (joke).
You should understand what exactly proxy's .get and .set do. Get will intercept any reading try of the object. Lets take your example:
p.set(1,2)
p.get(1)
On the first line we: read from object property with name set and then try to invoke it as function
On the second line we read from object property with name get and then try to invoke it as a function.
If you will try this code:
p.val = 5;
then you will try to set 5 to the target with name val and setter will fire.
This how proxy's setter and getter work.
So, to achive desired behavior, check the property name and return the function with some additional implementation. And do not forget to call original function.
Somth like this:
get: (o, k) => {
if (k==='get') return Reflect.get(o, k).bind(o);
if (k==='set') return function(v){Reflect.set(o, k, v)}
}
Hope this helps.
Update:
let obj = {
take: (v) => v
};
let handler = {
get: (target, key) => {
if (key === 'take') {
return function(v) {
console.log(`logger says: function ${key} was called with argument: ${v}`);
}
return target[key];
}
}
};
let proxy = new Proxy(obj, handler);
proxy.take(5);
proxy.take(3);
I'm running into a situation where I basically need to do something like below.
observableFoo
.flatMap(bar(param[0]))
.flatMap(bar(param[1]))
//...
.flatMap(bar(param[N]))
function bar(param){
var fn = function(...){
// return some observable depending on param
}
return fn;
}
where N is only known at runtime. How can I implement it in a "functional manner" without resorting to an imperative for-loop or some mutable variable?
A functional way would be to fold over the param array (using JavaScript's .reduce method):
param.reduce(function(o, p) {
return o.flatMap(bar(p)); // probably inline the bar call
}, observableFoo);
var i = 0;
observableFoo
.expand(function (x) {
return Rx.Observable.just(x).flatMap(bar(param[i++]));
})
.take(N)
Check the documentation for expand, and this JSFiddle for an example. The i var here is indeed a mutable variable, but one just needs to decide whether it is a problem or if it is harmless.
In the C++ world, we often have this kind of API design pattern:
bool foo(int input1, int input2, int& output1, int& output2, ClassA& outputObj);
The function has a set of input parameters as well as output parameters. The return value indicates if the function succeeds or fails.
An example of this API is:
int input1=0;
int input2=1;
int output1=0;
int output2=1;
ClassA a = new ClassA(...);
bool r = foo(input1, input2, output1, output2, a);
However, in the JavaScript, we have no simple way to simulate "change the primitive argument by reference" behavior. If we wrap the primitive type (number, string etc.) using objects. The API will be ugly.
Any idea about how to design an elegant API using JavaScript with input parameters, output parameters, return values? There might be objects and primitive types in the parameters.
Don't pass output variables as parameters. Rather return them as an array:
function foo(input1, input2) {
...
return [output1, output2, outputObj];
}
You may also return a more descriptive object, for example:
function foo(input1, input2) {
...
return {importantStuff: output1, somethingElse: output2, completeObject: outputObj};
}
Use throw to indicate error.
Bottom line: the way it's done in C++ is not necessarily the way it should be done in Javascript.
You seem to be expecting Javascript to have references (&), like C++. In Javascript, every object is a reference and these are passed by value.
So, if you have:
var foo = {prop: 'foo'};
function f(x) {
x.prop = 'bar';
}
f(foo);
console.log(foo); // Will display {prop: 'bar'}.
In C++ parlance, objects are passed by reference. Read this for full understanding.
Is there a way to allow "unlimited" vars for a function in JavaScript?
Example:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Sure, just use the arguments object.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
In (most) recent browsers, you can accept variable number of arguments with this syntax:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Here's a small example:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
0: "a"
1: "b"
2: "c"
3: "d"
length: 4
Documentation and more examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
Another option is to pass in your arguments in a context object.
function load(context)
{
// do whatever with context.name, context.address, etc
}
and use it like this
load({name:'Ken',address:'secret',unused:true})
This has the advantage that you can add as many named arguments as you want, and the function can use them (or not) as it sees fit.
I agree with Ken's answer as being the most dynamic and I like to take it a step further. If it's a function that you call multiple times with different arguments - I use Ken's design but then add default values:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
This way, if you have many parameters but don't necessarily need to set them with each call to the function, you can simply specify the non-defaults. For the extend method, you can use jQuery's extend method ($.extend()), craft your own or use the following:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
This will merge the context object with the defaults and fill in any undefined values in your object with the defaults.
It is preferable to use rest parameter syntax as Ramast pointed out.
function (a, b, ...args) {}
I just want to add some nice property of the ...args argument
It is an array, and not an object like arguments. This allows you to apply functions like map or sort directly.
It does not include all parameters but only the one passed from it on. E.g. function (a, b, ...args) in this case args contains
argument 3 to arguments.length
Yes, just like this :
function load()
{
var var0 = arguments[0];
var var1 = arguments[1];
}
load(1,2);
As mentioned already, you can use the arguments object to retrieve a variable number of function parameters.
If you want to call another function with the same arguments, use apply. You can even add or remove arguments by converting arguments to an array. For example, this function inserts some text before logging to console:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Although I generally agree that the named arguments approach is useful and flexible (unless you care about the order, in which case arguments is easiest), I do have concerns about the cost of the mbeasley approach (using defaults and extends). This is an extreme amount of cost to take for pulling default values. First, the defaults are defined inside the function, so they are repopulated on every call. Second, you can easily read out the named values and set the defaults at the same time using ||. There is no need to create and merge yet another new object to get this information.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
This is roughly the same amount of code (maybe slightly more), but should be a fraction of the runtime cost.
While #roufamatic did show use of the arguments keyword and #Ken showed a great example of an object for usage I feel neither truly addressed what is going on in this instance and may confuse future readers or instill a bad practice as not explicitly stating a function/method is intended to take a variable amount of arguments/parameters.
function varyArg () {
return arguments[0] + arguments[1];
}
When another developer is looking through your code is it very easy to assume this function does not take parameters. Especially if that developer is not privy to the arguments keyword. Because of this it is a good idea to follow a style guideline and be consistent. I will be using Google's for all examples.
Let's explicitly state the same function has variable parameters:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Object parameter VS var_args
There may be times when an object is needed as it is the only approved and considered best practice method of an data map. Associative arrays are frowned upon and discouraged.
SIDENOTE: The arguments keyword actually returns back an object using numbers as the key. The prototypal inheritance is also the object family. See end of answer for proper array usage in JS
In this case we can explicitly state this also. Note: this naming convention is not provided by Google but is an example of explicit declaration of a param's type. This is important if you are looking to create a more strict typed pattern in your code.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Which one to choose?
This depends on your function's and program's needs. If for instance you are simply looking to return a value base on an iterative process across all arguments passed then most certainly stick with the arguments keyword. If you need definition to your arguments and mapping of the data then the object method is the way to go. Let's look at two examples and then we're done!
Arguments usage
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
Object usage
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Accessing an array instead of an object ("...args" The rest parameter)
As mentioned up top of the answer the arguments keyword actually returns an object. Because of this any method you want to use for an array will have to be called. An example of this:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
To avoid this use the rest parameter:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Use the arguments object when inside the function to have access to all arguments passed in.
Be aware that passing an Object with named properties as Ken suggested adds the cost of allocating and releasing the temporary object to every call. Passing normal arguments by value or reference will generally be the most efficient. For many applications though the performance is not critical but for some it can be.
Use array and then you can use how many parameters you need. For example, calculate the average of the number elements of an array:
function fncAverage(sample) {
var lenghtSample = sample.length;
var elementsSum = 0;
for (var i = 0; i < lenghtSample; i++) {
elementsSum = Number(elementsSum) + Number(sample[i]);
}
average = elementsSum / lenghtSample
return (average);
}
console.log(fncAverage([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); // results 5.5
let mySample = [10, 20, 30, 40];
console.log(fncAverage(mySample)); // results 25
//try your own arrays of numbers