Javascript: Compose a function with argument placement instructions for each composition - javascript

I'm looking for a javascript function that can:
Condition (I)
compose another function when it does not have recursion in its definition, kind of like in maths when the function is given a power, but with multiple arguments possible in the first input - e.g. with a (math) function f:
f(x) := x+2
f5(x) = f(f(f(f(f(x))))) = x+10
Condition (II)
Or maybe even input custom arguments into each step of composition:
(52)2)2=
Math.pow(Math.pow(Math.pow(5,2),2),2) = Math.pow.pow([5,2],2,["r",2]])
//first arg set, how times the next, 2nd arg set - "r" stands for recursion -
//that argument will be occupied by the same function
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,2]]) //-> 390625
2((52)3)=
Math.pow(2,Math.pow(Math.pow(5,2),3)) = Math.pow.pow([5,2],["r",2],["r",3],[2,"r"])
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,3]]) //-> 244140625
_.supercompose(Math.pow,[[5,2],[_,2],[_,3],[2,_]]) //-> Infinity (bigger than the max. number)
Note: The above are just templates, the resulting function doesn't have to have the exact arguments, but the more close to this (or creative, for example, a possibility of branching off like this ->[2,4,"r",4,2,"r"], which would also be complicated) the better.
I've been attempting to do at least (I) with Function.prototype, I came up with this:
Object.defineProperty(Function.prototype,"pow",{writable:true});
//Just so the function not enumerable using a for-in loop (my habit)
function forceSlice(context,argsArr)
{returnArray.prototype.slice.apply(context,argsArr)}
Function.prototype.pow = function(power)
{
var args=power<2?forceSlice(arguments,[1]):
[this.pow.apply(this,[power-1].concat(forceSlice(arguments,[1])))];
return this.apply(0,args);
}
//Usage:
function square(a){return a*a;}
square.pow(4,2) //65536
function addThree(a,b){return a+(b||3); }
// gives a+b when b exists and isn't 0, else gives a+3
addThree.pow(3,5,4) //15 (((5+4)+3)+3)
Worst case, I might just go with eval, which I haven't figured out yet too. :/
Edit: Underscore.js, when played around with a bit, can fulfill both conditions.
I came up with this, which is close to done, but I can't get it to work:
_.partialApply = function(func,argList){_.partial.apply(_,[func].concat(argList))}
_.supercompose = function(func,instructions)
{
_.reduce(_.rest(instructions),function(memo,value)
{
return _.partialApply(_.partialApply(func, value),memo)();
},_.first(instructions))
}
//Usage:
_.supercompose(Math.pow,[[3,2],[_,2]]) //should be 81, instead throws "undefined is not a function"
Edit: jluckin's cleareance of terms (recursion-> function composition)
Edit: made example function return number instead of array

The term you are looking for is called function composition, not necessarily recursion. You can apply function composition in javascript easily since you can pass a function as an argument.
I created a small function called compose, which takes a function, an initial value, and the number of times to compose the function.
function compose(myFunction, initialValue, numberOfCompositions) {
if (numberOfCompositions === 1) {
return myFunction(initialValue);
}
else {
return compose(myFunction, myFunction(initialValue), --numberOfCompositions);
}
}
When this function is evaluated, you pass in some function f(x), some initial x0, and the repeat count. For example, numberOfCompositions = 3 gives f(f(f(x)));
If there is one composition, then f(x) is returned. If there are two compositions, compose returns f(x) with f(x) replacing x as the argument, with 1 passed in as the composition so it will evaluate f(f(x)).
This pattern holds for any number of compositions.
Since functions are treated as objects and can be passed as arguments of functions, this method basically wraps your "non-recursive" functions as recursive functions to allow composition.

Success(simplicity wins):
_.supercompose = function (func,instructions,context)
{
var val;
for(var i = 0; i < instructions.length; i++)
{
val = _.partial.apply(_,[func].concat(instructions[i])).apply(context||this,val?[val]:[]);
}
return val;
}
//Usage (with a function constructor for operations):
_.op = function(o){return Function.apply(this,"abcdefghijklmnopqrstuvwxyz".split("").concat(["return " + o]))}
_.op("a+b")(3,5) //-> 8
_.op("a*b")(3,5) //-> 15
_.supercompose(_.op("(a+b)*c*(d||1)"),[[1,2,3],[-5,_,1],[1,2,_,3]])
//-> (1+2)*((-5+((1+2)*3))*1)*3 -> 36

Related

Closure with a Lazy Adder Function

I'm stuck on a problem that uses a closure function to add the arguments of subsequent functions into a sum function:
Write a function named: lazyAdder(firstNum). The lazyAdder function
will accept a number and return a function. When the function returned
by lazyAdder is invoked it will again accept a number, (secondNum),
and then return a function. When the last mentioned function is
invoked with a number, (thirdNum), it will FINALLY return a number.
See below for examples!
Example 1:
let firstAdd = lazyAdder(1);
let secondAdd = firstAdd(2);
let sum = secondAdd(3);
console.log(sum); // prints 6
Example 2:
let func1 = lazyAdder(10);
let func2 = func1(20);
let total = func2(3);
console.log(total); // prints 33
I tried:
const lazyAdder = f => g => h => x => f(g(h))(h(x));
Thinking it takes in two function inputs (firstNum + secondNum = sum1), then adds a third (thirdNum + sum1 = sum2).
This did invoke the function twice; however, it did not return the sum - it returned an anonymous function.
If I get it correctly, what you are tasked to do is to perform a sum in a sequence of evaluations (i.e. pass arguments at different times). In a non-lazy approach, you would simply make a function sum which takes 3 parameters x, y and z and sum this: sum(1, 2, 3) = 7. Now to do this the "lazy" way, you have to perform an operation on this function called currying. I suggest reading up on this, as this is essentially what is asked.
Currying such a function can be done quite easily in JavaScript. As you showed, you can just chain the arguments in a function declaration:
const func = arg1 => arg2 => arg3 => ... // Some logic performed here
Now you can call this function 3 times until it returns something other than a closure; a value.
How do you make sure that when you func(1)(2)(3) it returns the sum, which is 6?
Since I suspect this is a homework assignment, I do not want to give you the plain answer. Therefore, it is up to you to define what logic should be put inside the function to sum these values. What is important is that the definition I gave, is already a definition of lazy evaluation.

Is there a possible way to check for second parentheses in a function?

I'm working on a Javascript challenge. The challenge is the code below in which you add the numbers provided together:
function addTogether() {
//I left this blank because I'm focused on checking for the second parentheses
}
However, if you tried to pass this addTogether(5)(7) to the function addTogether(), it would be difficult to get the second parentheses.
However, you can get both parentheses if you write this code:
function addTogether() {
//get first parenteses
let first = arguments;
//get second parentheses
let second = function() {
return arguments;
};
}
But my question is how do you check if there's a second parentheses? Because I'm passing other data such as addTogether(2,3). In other words, I might be passing some with one parentheses and another with two parentheses to the function addTogether()
There is no way to check, unless you're parsing the source code, but your function can optionally accept second argument and if it's provided return the sum, otherwise return a function
const addTogether = (a, opt) => opt ? a + opt : b => a + b
console.log("addTogether(1,3) => ", addTogether(1,3))
console.log("addTogether(4)(6) => ", addTogether(4)(6))
Naive implementation using function that coerces to number.
Using reduce to calculate sums. Overriding ##toPrimitive to create function that coerces to value of add. Recursive call to generate recursively chainable callable number coercable functions.
Check ECMAScript specs if you want to customize behavior further. You will need to understand the conversion path.
function sum(...args) {
const first = args.reduce((sum,x)=>sum+x,0)
const second = function(...args) {return sum(first, ...args)}
second[Symbol.toPrimitive] = function(){return first}
return second
}
console.log(
1+sum(1)(2)+sum(1)+sum(3),
sum(1,1,2) (1,3)(0)(0)+sum(0,-1,1,0),
sum(1)(1)(2)(1)(3)(0)(0)(-1,1)(0)+sum()
)

How can this function work with a missing parameter

How can callback function work with one parameter when it requires 2 (selector and data) to go? Why doesn't it throw an error?
let links = document.querySelectorAll("a");
links.forEach(function(link){
link.addEventListener("click",function(e){
e.preventDefault();
ajax("get",e.target.href,render)
})
})
function ajax(url,metodo,callback){
let xhr = new XMLHttpRequest
xhr.open(metodo,url)
xhr.addEventListener("load",function(){
if(xhr.status==200){
callback(xhr.response)
}
})
xhr.send()
}
function render(selector,data){
document.querySelector(selector).innerHTML = data
}
In javascript, it is not necessary to call with same number of parameters as defined in function definition. If we do not define a default parameter value in function definition, then parameter becomes type of undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
Default function parameters allow formal parameters to be initialized
with default values if no value or undefined is passed.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Starting with ECMAScript 2015, there are two new kinds of parameters:
default parameters and rest parameters.
Default parameters: In JavaScript, parameters of functions default to
undefined. However, in some situations it might be useful to set a
different default value. This is where default parameters can help.
In the past, the general strategy for setting defaults was to test
parameter values in the body of the function and assign a value if
they are undefined. If in the following example, no value is provided
for b in the call, its value would be undefined when evaluating a*b
and the call to multiply would have returned NaN. However, this is
caught with the second line in this example:
function multiply(a, b) {
b = typeof b !== 'undefined' ? b : 1;
return a * b;
}
multiply(5); // 5
With default parameters, the check in the function body is no longer necessary. Now, you can simply put 1 as the default
value for b in the function head:
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
For more details, see default parameters in the reference.
Rest parameters: The rest parameter syntax allows us to represent an
indefinite number of arguments as an array. In the example, we use the
rest parameters to collect arguments from the second one to the end.
We then multiply them by the first one.
function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
Argument Object:
Using the arguments object, you can call a function with more
arguments than it is formally declared to accept. This is often useful
if you don't know in advance how many arguments will be passed to the
function. You can use arguments.length to determine the number of
arguments actually passed to the function, and then access each
argument using the arguments object.
For example, consider a function that concatenates several strings.
The only formal argument for the function is a string that specifies
the characters that separate the items to concatenate. The function is
defined as follows:
function myConcat(separator) {
var result = ''; // initialize list
var i;
// iterate through arguments
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
You can pass any number of arguments to this function, and it
concatenates each argument into a string "list":
// returns "red, orange, blue, "
myConcat(', ', 'red', 'orange', 'blue');
// returns "elephant; giraffe; lion; cheetah; "
myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah');
// returns "sage. basil. oregano. pepper. parsley. "
myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley');
To make it throw error, if same number of argument is not passed in function, typescript can be used.

Is there a JavaScript equivalent for C# 'params'?

I need a method that can have an arbitrary number of parameters. In C# we have the params statement. Do we have anything similar in JavaScript?
There is the arguments collection, which contains all arguments passed to the function.
There is a) no need to specify "optional" arguments in the function signature and b) any function accepts any number of parameters.
function foo() {
console.log(arguments);
}
foo(1,2,3,4); // logs [1, 2, 3, 4]
Likewise, there is no need to supply "required" arguments in a function call:
function foo(a, b, c, d) {
console.log(arguments);
}
foo(1,2); // logs [1, 2]
Any argument named in the signature but not supplied in the function call will be undefined.
Note that arguments behaves like an Array, but technically it isn't one. For example, you can call arguments[0], but you can't call arguments.slice(). What you can do to get around this is using the Array prototype:
Array.prototype.slice.call(arguments, 1, 2);
The so-called rest parameter ... is a new (ES6+) addition to the language and makes working with variadic functions more comfortable. #ArunCM's answer explains it.
I know this thread is too old but I believe something is missing here.
There is Rest parameter (introduced in ECMAScript 6) which will allow us to represent an indefinite number of arguments as an array.
It always returns an array. Which means even in defensive JavaScript land, it’s ok to do things like check .length of rest without guards.
Syntax :
function(a, b, ...theArgs) {
// ...
}
There are three main differences between rest parameters and the arguments object:
rest parameters are only the ones that haven't been given a separate name, while the arguments object contains all arguments passed to the function
the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
the arguments object has additional functionality specific to itself (like the callee property).
Additional reading : Spread
function f(x, ...y) {
// y is an Array
return x * y.length;
}
console.log("Expected result : 3*2 = 6 & Actual result : " + f(3, "hello", true));
console.log("Expected result : 3*4 = 12 & Actual result : " + f(3, "a", true, "b", 1));
//here we are not passing anything to "y" but its still safe to check .length of "y" because it always return an array.
console.log("Expected result : 3*0 = 0 & Actual result : " + f(3));
Yes. arguments.
function concatStrings () {
var str = '';
for (var i = 0; i < arguments.length; i++) {
str += arguments[i];
}
return str;
}
Be aware that arguments isn't an array, so it doesn't have methods like join or push. It's just an array-like object (with numerical properties and a length property) so it can be iterated through.
JavaScript has arguments object inside functions. It contains of all params passed to the function.
More info
It is some sort of implicit in the special variable "arguments". Use like this:
function something(arg1, arg2) {
for (var i = 0; i < arguments.length; i++) {
var x = arguments[i];
}
}
Then you can call it like something(1, 2, 3, 'a', 'b', 'c')
More examples here: http://www.jtricks.com/javascript_tutorials/varargs.html
Javascript functions can accept any number of parameters by default. You can see them with the arguments variable.
See here.

What is this javascript code doing?

this.String = {
Get : function (val) {
return function() {
return val;
}
}
};
What is the ':' doing?
this.String = {} specifies an object. Get is a property of that object. In javascript, object properties and their values are separated by a colon ':'.
So, per the example, you would call the function like this
this.String.Get('some string');
More examples:
var foo = {
bar : 'foobar',
other : {
a : 'wowza'
}
}
alert(foo.bar); //alerts 'foobar'
alert(foo.other.a) //alerts 'wowza'
Others have already explained what this code does. It creates an object (called this.String) that contains a single function (called Get). I'd like to explain when you could use this function.
This function can be useful in cases where you need a higher order function (that is a function that expects another function as its argument).
Say you have a function that does something to each element of an Array, lets call it map. You could use this function like so:
function inc (x)
{
return x + 1;
}
var arr = [1, 2, 3];
var newArr = arr.map(inc);
What the map function will do, is create a new array containing the values [2, 3, 4]. It will do this by calling the function inc with each element of the array.
Now, if you use this method a lot, you might continuously be calling map with all sorts of arguments:
arr.map(inc); // to increase each element
arr.map(even); // to create a list of booleans (even or odd)
arr.map(toString); // to create a list of strings
If for some reason you'd want to replace the entire array with the same string (but keeping the array of the same size), you could call it like so:
arr.map(this.String.Get("my String"));
This will create a new array of the same size as arr, but just containing the string "my String" over and over again.
Note that in some languages, this function is predefined and called const or constant (since it will always return the same value, each time you call it, no matter what its arguments are).
Now, if you think that this example isn't very useful, I would agree with you. But there are cases, when programming with higher order functions, when this technique is used.
For example, it can be useful if you have a tree you want to 'clear' of its values but keep the structure of the tree. You could do tree.map(this.String.Get("default value")) and get a whole new tree is created that has the exact same shape as the original, but none of its values.
It assigns an object that has a property "Get" to this.String. "Get" is assigned an anonymous function, which will return a function that just returns the argument that was given to the first returning function. Sounds strange, but here is how it can be used:
var ten = this.String["Get"](10)();
ten will then contain a 10. Instead, you could have written the equivalent
var ten = this.String.Get(10)();
// saving the returned function can have more use:
var generatingFunction = this.String.Get("something");
alert(generatingFunction()); // displays "something"
That is, : just assigns some value to a property.
This answer may be a bit superflous since Tom's is a good answer but just to boil it down and be complete:-
this.String = {};
Adds an object to the current object with the property name of String.
var fn = function(val) {
return function() { return(val); }
}
Returns a function from a closure which in turn returns the parameter used in creating the closure. Hence:-
var fnInner = fn("Hello World!");
alert(fnInner()); // Displays Hello World!
In combination then:-
this.String = { Get: function(val) {
return function() { return(val); }
}
Adds an object to the current object with the property name of String that has a method called Get that returns a function from a closure which in turn returns the parameter used in creating the closure.
var fnInner = this.String.Get("Yasso!");
alert(fnInner()); //displays Yasso!

Categories

Resources