I'm trying to mimic lazy evaluation in JavaScript by evaluating one specific function call in an expression, while leaving the other functions as-is. Is it possible to evaluate just one function in an expression without evaluating the other functions (so that all of the other function calls in the expression are left as-is)?
Here's the function I'm trying to implement:
function evaluateSpecificFunction(theExpression, functionsToEvaluate){
//Evaluate one specific function in the expression, and return the new expression, with one specific function being evaluated
}
For example:
evaluateSpecificFunction("addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)", addTwoNumbers);
//This should return "3 + getGreatestPrimeFactor(10)", since only one of the functions is being evaluated
evaluateSpecificFunction("addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)", getGreatestPrimeFactor);
//This should return "addTwoNumbers(1, 2) + 5";
What you can do is play with replace and a regular expression :
function getGreatestPrimeFactor(n) {
return n*2;
}
function transform(s, f) {
return s.replace(new RegExp(f+"\\(([^\\)]*)\\)", "g"), function(m, args) {
return window[f].apply(null, args.split(',').map(function(v){
return parseFloat(v)
}));
});
}
var result = transform(
"addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)",
"getGreatestPrimeFactor"
);
This example assume you deal only with numeric parameters.
Demonstration (open the console)
Of course this code mostly demonstrate the idea, you should, for example, store the functions in a dedicated object and not the global context (window).
EDIT : the new version can handle more than one replacement.
Related
This question already has answers here:
What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?
(14 answers)
Closed 6 years ago.
I have the following arrow function
if( rowCheckStatuses.reduce((a, b) => a + b, 0) ){}
rowCheckStatuses is an array of 1's and 0's, this arrow function adds them all up to produce a number. This number acts as a boolean to determine whether or not there is at least one "1" in the array.
The issue is, I don't really understand how arrow functions work, and my IDE thinks it's bad syntax and refuses to check the rest of my document for syntax errors.
How would I go about converting this to a regular function to alleviate both issues?
An arrow function can usually be converted by replacing
(<args>) => <body>
with
function(<args>) { return <body>; }
So yours would be
rowCheckStatuses.reduce(function(a, b) { return a + b; }, 0)
There are exceptions to this rule so it's important that you read up on arrow functions if you want to know all of the differences. You should also note that arrow functions have a lexical this.
You can refactor it as:
if( rowCheckStatuses.reduce(function(a, b){return a + b}, 0)
The initial accumulator isn't necessary (unless you expect the array to be empty sometimes), it could be:
if( rowCheckStatuses.reduce(function(a, b){return a + b})
This number acts as a boolean to determine whether or not there is at least one "1" in the array
It might be faster (and clearer) to use:
if( rowCheckStatuses.some(function(a){return a == 1}))
which will return true if there are any 1s in rowCheckStatuses and will return as soon as one is encountered. Another alternative is indexOf:
if( rowCheckStatuses.indexOf(1) != -1)
Lots of alternatives.
Replacing arrow functions with regular functions is usually unproblematic:
var f = x => y;
var g = function(x) { return y; }
Or, in your specific example:
rowCheckStatuses.reduce((a, b) => a + b, 0);
rowCheckStatuses.reduce(function(a, b) { return a + b; }, 0);
However, be aware of the exceptions:
Arrow functions don't bind a this value. Accessing this in an arrow function might thus return the value of the enclosing execution context's this:
function MyClass() {}
MyClass.prototype.f = () => this;
MyClass.prototype.g = function() { return this; }
myClass = new MyClass();
console.log(myClass.f()); // logs `Window`
console.log(myClass.g()); // logs `myClass`
Arrow functions also don't have access to a local arguments object. Accessing arguments in an arrow function might e. g. return the arguments of an enclosing function:
function test() {
var f = () => arguments;
var g = function() { return arguments; }
console.log(f()); // logs test's arguments
console.log(g()); // logs g's arguments
}
test('x');
The same holds for new.target and super. See also What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
i am very new to ES6.
Trying to go through some tests to learn.
Please help me on this on what should be the implementation to pass the tests.
// dependencies:
const expect = require('chai').expect;
// implement this:
function b(x){
// return "b"+ x;
// return (x) => "bo" + x;
}
// unit tests:
describe("implement function b", function() {
it("SHOULD work for the following cases", function() {
console.log(b()("m"));
expect(b("m")).to.equal("bm");
expect(b()("m")).to.equal("bom");
expect(b()()("m")).to.equal("boom");
expect(b()()()("m")).to.equal("booom");
expect(b()()()()("t")).to.equal("boooot");
});
});
This is possible but a bit weird and I would never do something like this in real life.
In general, a function that returns a function is called a "second-order" function. A function that returns a function that returns a function is a "third-order" function. What you're trying to do is write a function that is has a different order depending on the arguments, which is really confusing to read and maintain.
Having said that, javascript isn't fussy about return types, so you can do it. Here's the code I'd use (uses ES6 default variables and recursion)
function b(lastLetter, prefix = "b") {
if (lastLetter) {
//if we're ending the chain, return everything so far with the last letter on the end
return prefix + lastLetter;
}
//if not, then return version of this function with a slightly longer prefix
return lastLetter => b(lastLetter, prefix + "o");
}
console.log( b("m") );
console.log( b()("m") );
console.log( b()()("m") );
console.log( b()()()()()()()("t") );
You can use a closure and named function expression, see comments. I don't like the repeated line but can't avoid it with this pattern.
function b(x) {
// On the first call, setup prefix
var prefix = 'b';
// End early if x provided on first call
if (x) return prefix + x;
// Otherwise, return a function that can be chained
return function foo(x){
prefix += 'o';
if (x) return prefix + x;
return foo;
}
}
console.log(b('m'));
console.log(b()('m'));
console.log(b()()('m'));
console.log(b()()()('m'));
console.log(b()()()()('t'));
The problems with this pattern are:
If no letter is provided in the last call, it returns a function. There's no way for a particular call to know it's the last.
If a call is made after a letter is provided, it will attempt to call a string, which will throw an error. Again, there's no way to stop the call once a letter is provided if the user attempts it.
Obviously, b has to return a function if no argument is passed to it. This function acts the same way: if no argument is passed to it, it returns itself. Moreover, we have to keep track of how many times our function was called.
The following solution creates an inner function which increments the count if its argument is falsy, otherwise it creates a string that consists of "b", "o" repeated as many times as the count specifies and the value of the argument:
const b = v => {
let n = 0; // this is our counter
const f = e => {
if (e !== undefined) {
// an argument was passed, return the correct value
return 'b' + 'o'.repeat(n) + e;
}
// no argument was passed, increment the counter and return the function
n += 1;
return f;
};
// call the function the first time with the initial value
return f(v);
};
console.log(b('m'));
console.log(b()('m'));
console.log(b()()('m'));
console.log(b()()()('m'));
console.log(b()()()('t'));
I'm learning javascript and I found this exercise:
function abc(a){
return(function(y){
return y--**--y+1;
})(++a)+a;
}
document.write(abc(2));
The output of that is 7 and I dont understand why, I searched information about nested functions and I didnt found anything....
How is "y" defined?
this function translates to:
//I've replaced the arguments and the vars with the actual values
function abc(){
function innerFunction(){
return (3 ** 1) + 1
}
return innerFunction(3) + 3
}
//or written differently
function abc(a){
function innerFunction(v){
//v--
var tmp1 = v;
v = v-1;
//--v
v = v-1;
var tmp2 = v;
return Math.pow(tmp1, tmp2) + 1;
}
a = a+1; //++a
return innerFunction(a) + a;
}
That is easy.
Function abc return (function(y){ return y--**--y+1; })(++a)+a
this means if a is 2 (function(3){ return y--**--y+1; }) + 2
This contains an immediately invoked function expression (IIFE).
Here's an example that might clarify how they work:
(function(x) { return x; })(10); // Returns 10
The value inside the parenthesis is used as the function's argument as soon as the function is defined. So, in this case, the function is set to return the argument, and immediately afterwards, it is given the value 10.
On your example, with some added whitespace:
return (function(y) {
return y-- ** --y + 1;
})(++a)
+ a
What's happening is the same. A function is being defined then, immediately afterwards, it receives the argument ++a. It will replace all instances of y by the value contained in ++a. Then, as that is returned, it goes through + a, so it adds a to the result.
I'm trying to write a JavaScript function that will integrate functions using Simpson's Rule. I fully understand the math behind Simpson's Rule, but I'm unsure of how to write a function that will integrate another function. Here's the code I'd like to implement:
integrate = function(leftBound, rightBound, numSubIntervals, expression) {
var a = leftBound,
b = rightBound,
n = numSubIntervals,
myFunc = expression;
/*implementation of simpson's rule..*/
return result;
}
My issue is that I don't know how to pass a mathematical expression (the function to be integrated) as a parameter without doing something like passing it as a string and using eval(), which is not something I want to do. I also don't want to use any third-party libraries. I want to write the function using vanilla JavaScript only. What am I missing here - is there an obvious solution to this?
Functions themselves can be arguments to other functions. For example:
integrate(0,5,10, function(x){
return x*x;
})
This example takes a function that takes a given X and squares it. Within integrate, you would call this function for given intervals of x to integrate this function using Simpson's rule.
Within integrate, the syntax for calling a function passed to it is:
var point = expression(x);
Where x is the value passed to the function named expression, and point is the return value of expression.
Here's my answer-version of my comment. You can pass the function as parameter and then call it from inside.
integrate = function(leftBound, rightBound, numSubIntervals, expression) {
var a = leftBound,
b = rightBound,
n = numSubIntervals,
myFunc = expression;
/*implementation of simpson's rule..*/
result = (b-a)/6 * (expression(a) + 4*f* ... );
return result;
}
var toIntegrate = function(x){
return 2*x*x*x - 3*x*x + 2*x - 1;
}
integrate(0, 10, 10, toIntegrate);
I just finished learning about functions and I'm a bit confused about using return statements and variables in functions.
function test1(frag1, frag2) {
return frag1 + frag2;
}
function test2(frag1, frag2) {
message = frag1 + frag2;
}
alert(test1("this one used", " a return"));
test2("this one used ", "a variable")
alert(message);
Other than calling test2 outside the alert, is there any difference between using return and putting what I need inside a variable? I was learning that to get data from a function, I had to use a return statement. So how does test2 work?
You can only use return to get one thing from a function, right? So, could I use test2 to get multiple things out? Like this:
function test2(a, b, c) {
message1 = a + b;
message2 = b + c;
message3 = a + c;
}
Or, am I just over thinking this/just wrong?
Thanks in advance.
[...] is there any difference between using return and putting what I need inside a variable?
Yes.
If you use global variables, e.g., variables not declared with a var in a function, that variable will be created in the global scope. This means you may accidentally overwrite a variable with the same name, and can lead to all sorts of difficult-to-diagnose bugs. Global scope is usually a Bad Thing.
test2 "works" because message is in the global scope, this available everywhere. Einstein would call this "spooky action at a distance", and it makes code much harder to reason about, e.g., "this variable has changed–how? Why? Where? Under what circumstances?" all become more difficult to answer.
Using return statements and keeping places where value modifications change centralized and contained within the smallest scope(s) possible make reasoning about what's happening much easier.
Avoiding global variables, such as "message" in your example, is a much much cleaner approach to programming.
Using function return values allows you to display multiple different messages without 'side effects'.
The side affect in this case is that the variable 'message' can only hold ONE message and display it at any given time.
Consider this (clean approach):
function sqr(n) {
return n * n;
}
function msg1() {
return "Hello 1";
}
function addIt(n1, n2) {
return n1 + n2;
}
alert(sqr(5));
alert(msg1());
alert(addIt(5, 5));
Its about scope. The reason the first example you provided works is because of the lack of scoping of message. If you define message as you did, it inherits the global window object, and therefore is accessible by everyone and everything:
function notSoPrivate(){
message = 'test';
}
console.log(message); // logs 'test'
However, if you preface the declaration of the variable with the word var, it scopes it locally to the object / function it is in:
function morePrivate(){
var message = 'test';
}
console.log(message); // logs undefined
This allows you to perform multiple actions within the function without polluting the global window object, which is highly recommended.
If you wanted to return multiple items, you can return an array:
function test2(a, b, c) {
var message1 = a + b,
message2 = b + c,
message3 = a + c;
return [message1,message2,message3];
}
console.log(test2(1,2,3)[0]); // logs 3
or my preferred option, an object:
function test2(a, b, c) {
var m1 = a + b,
m2 = b + c,
m3 = a + c;
return {
message1:m1,
message2:m2,
message3:m3
};
}
console.log(test2(1,2,3).message1); // logs 3
Hopefully this helped!
There is mainly two differences between using a return value and using a variable for the output:
It's a lot easier to follow what the code does when you use a return value.
To return a value in a variable it has to be global, and you should try to keep the use of global variables to a minimum.
When you use a variable for output, you need to know where the function puts the value to be able to follow the code. Just looking at the code that calls the function gives no hint that there is a relation between the function and the output:
test2("this one used ", "a variable")
; oh? where did message come from all of a sudden?
alert(message);
When you use a return value it's clear that the value comes from the function, so looking at the code tells you all you need to know on how the output is delivered:
var message = test2("this one used ", "a variable")
alert(message);
If you want to return multiple values from a function you can use an array or an object:
function test2(a, b, c) {
return {
message1: a + b,
message2: b + c,
message3: a + c
};
}
You still need to know what the object contains to use the return value, but at least it's clearly visible how the output is delivered:
var o = test2("See how ", "I control where ", "it goes");
alert(o.message2);