Hi I am having an issue with deciding how to store/calculate a value. The value is this case is dynamically generated by executing a javascript function that is stored in a mysql database.
The company I work for originally did this because other values that are used by the stored javascript function can be changed and because this is done by a AJAX request, the value needs to be calculated on the clients side. Somehow this doesn't feel right, and I think there has to be a better way to store this.
Now I am not sure how I should solve this, but I hope some of you can point me in the right direction.
I hope I explained the problem clear enough.
EDIT: An example.
There is a value x that needs to be calculated and currently this happens.
function example(){
if(y == true){
return 0;
}
var result = z / areaM2;
if(result > 100){
return 1;
}
else{
return 2;
}
}
x = example();
y, z and areaM2 are actual stored variables.
You should only save the values that can change, not the function itself, even if it could change. In the latter case you'd need to provide multiple functions in a JavaScript file and have a property stored in your DB to define which function to use.
Related
Suppose I want to define a "useful" function that takes a THREE.Vector2 as well as some scaler values as inputs. What's the best syntax for defining the function if I want other people to easily understand the types of the parameters that need to be passed into the function? Sample (that doesn't work):
export function clipToBox(v: THREE.Vector2, boxWidth, boxHeight) {
const clippedVector = new THREE.Vector2
// Do some clever clipping math...
return clippedVector
}
Example of what we want users of our function to see when editing
Google provides an example of optimising a custom formula to recurse over an array where there is one. It helps with the whole efficiency thing The example provided from the Apps Script Page shows the an example where there is 1 parameter, as:
function DOUBLE(input) {
if (input.map) { // Test whether input is an array.
return input.map(DOUBLE); // Recurse over array if so.
} else {
return input * 2;
}
}
What if there are 2 or more parameters? How can we still recurse?
Thank you for your responses. The post to which TheMaster refers is probably right, but to be honest, I don't completely understand it. I have resolved my issue by referring back to Google's pages again. To add further to Ghost's question, I'd like to have one parameter as an array and other other a single constant - sorry for the confusion, I'll be sure to put more thoughts into my future questions.
My updated prototype formula looks like this:
function DOSOMETHING(x, y) {
return Array.isArray(x) ?
x.map(i => i.map(cell => cell * y)) :
x * y;
}
Happy to report it actually does what I want it to. x can be a single number or an array. y can only be a single integer in this case.
Since my original post, Google updated their pages to show the function using ternary operator, which made it easier for me to read & understand.
I have a very simple if then statement that is not working as expected and I can't figure out why.
This is a subsection of code that I was working and have broken it down to the most basic script that is not working.
var x = 2;
if(x = 1)
{
Logger.log("July");
}
Logger.log(x);
I have hard coded x =2 and said if x =1 then log the word "July" and also logged the value of x.. after running my log shows July and 1. Both values are wrong. What am I missing?
Google Apps Script is based on JavaScript.
= is used for assigning in JavaScript, so currently you're using = to define your variable var x = 2, then re-assigning x = 1 in your if statement, which is why it's returning true.
You need to use == or === in your if statement when trying to compare values. See documentation below to read up on which you should use for your purpose and why.
Reference:
JavaScript Equals Operators
You are missing the ==. Explanation:
single = is used to assign a variable
double == is used to compare not strictly two variables
triple === is used to compare strictly two variables (the types are also compared)
var x = 2;
if(x == 1) {
Logger.log("July");
}
Logger.log(x);
If you want to learn the basis of javascript (the language used in google app scripts) -- take the codecademy recommended introduction course here.
In my app i need to allow the user to add their own math formulas, can use operators and call variables. There is anyway to validate if a user write wrong a variable or a unknown variable to show an error?
I have and example here, you have some scope variables in the top of the controller. A minor difference, if I insert an invalid variable in the example it shows null, but in my code appears in blank.
Any suggestions?
Well honestly, if you weren't lazily throwing this stuff in eval, you could easily parse it yourself I recon.
How about removing all whitespaces, and interating over every single character?
I mean as long as there are no variables like aa or ab, you can just check like.
for (var i = 0; i < answer.length ; i++) {
if (!isvalidParamOrOperator(answer[i])) {
//can show error at position i+1;
return false;
}
}
with isValidParamOrOperator being something like
function(str) {
return "1234567890ab".indexOf(str);
}
Of course it becomes a little bit more complicated at longer params, but you'd be able to create something that splits on all operators like + - spaces & numbers. And then you'll have a list of all params which you can check. which should probably be checked on an array instead of my current suggestion, but this shouldn't be hard after you implement something like this.
I'd like to use Object.assign to "upgrade" an object with new methods temporarily, and then remove those methods when I'm done using them. An example will clarify:
Say we have a mixin that allows us to calculate the average of an array:
var ArrayUtilMixin = {
avg() {
let sum = this.reduce( (prev, v) => {return prev + v}, 0);
return sum / this.length;
}
};
Our client code uses this like so:
let myArr = [0,3,2,4,88];
// now I am in a context where I want to average this array,
// so I dynamically add the ability with Object.assign
Object.assign(myArr, ArrayUtilMixin);
let avg = myArr.avg();
// do some stuff here with the average
// now we're done, we want declutter the myArr object
// and remove the no longer needed avg() method
Object.unassign(myArr, ArrayUtilMixin); // <-- CAN WE DO THIS SOMEHOW?
Is there any way to accomplish this? If not, am I using the wrong language feature for what I really want -- that ability to dynamically add and remove object methods at runtime, depending on context.
Is there any way to accomplish this?
There are some, but I think none of them does exactly what you want to do:
use Object.assign, then afterwards delete the new properties
Object.unassign = function(o, mixin) {
for (var p in mixin)
delete o[p]; // deletes own properties only, so don't fear
return o;
}
This doesn't work well when you have overwritten own methods/properties of course.
alter the prototype chain of the object you want to extend
function extend(o, mixin) {
var m = Object.assign({}, mixin);
Object.setPrototypeOf(m, Object.getPrototypeOf(o));
Object.setPrototypeOf(o, m);
return o;
}
function unextend(o) {
Object.setPrototypeOf(o, Object.getPrototypeOf(Object.getPrototypeOf(o)));
return o;
}
The advantage of this approach is that own properties stay own properties, so assignments on the object will work as usual. There are some languages that endorse this pattern (and combine it with multiple inheritance), but I'm not sure how well it really works. Of course, modifying the prototype chain is a really bad idea in JavaScript.
prepend to the prototype chain
function extended(o, mixin) {
return Object.assign(Object.create(o), mixin);
}
This creates a new object with the mixin methods that inherits from the actual object. You'd "unextend" by just throwing away the temporary one, and use the old again (not exactly the usage pattern you had in mind I guess?) - you can hide this fact by storing the old one in a property and "unwrap" with a unextend() function.
Of course, the drawback of this otherwise simple and efficient pattern is that assignments to the temporary object don't work. They would create new, own properties instead of modifying the actual object, and would get thrown away once you "unextend". This doesn't matter for your avg method, and can even be utilised for some mixins, but you might not want this.
If not, am I using the wrong language feature
It's quite possible that there is no language feature for this.
The most common advice for cases like this is to construct a wrapper object (e.g. around DOM objects), which acts as a proxy between the user and the actual object. The API of the wrapper is completely different from the wrapped object's one though; this is not a simple "extension".