Java Script practice - bundleArgsFunction - javascript

I am relatively new to coding, and I have been doing some practice problems for javascript for the sake of practice. There is this one problem that I am stuck on about implementing the bind function. Essentially, I need to implement a function called bundleArgs with two parameters: a function fn to get args bundled with and args1, args2 to argsn - any numbers of args that will automatically get filled in when the output function is used. bundleArgs is essentially supposed to return a version of the original fn that can take any number of arguments, but when used, will use the args1, args2 to argsn as the first parameters to fn, filling in the new arguments afterwards. I attempted doing this with the bind function, since it basically makes your arguments pre-filled, however I am supposed to implement this WITHOUT using bind, and that is essentially where I am stuck. Example of the output: // example, you have a function that surrounds text with other text
function surroundText(surrounding, text) {
return [surrounding, text, surrounding].join(" ")
}
// but you know you're going to use it for one thing only
const makeCool = bundleArgs(surroundText, "~x~X~x~")
// save yourself some time
console.log(makeCool("i guess")) // ~x~X~x~ i guess ~x~X~x~
// again w/ leftovers
function repeatLetter(letter, times) {
Array(times).fill(letter).join('');
}
// fix 1 of 2 arguments to 'r'
rrrrrollWithIt = bundleArgs(repeatLetter, 'r');
// resulting function has only one arg now
rrrrrollWithIt(10) // rrrrrrrrrr

Related

Javascript: Flexibility of function parameters?

The description of Javascript function parameters on W3Schools wasn't very clear, so I just want to clarify.
From my understanding, there isn't a type restriction; the "real value" of the parameters are passed into the method. Is there a way to pass objects or elements? Or is that what is meant by "real value"?
For example:
The function displayText meant to take input text and set a display to show a new word in the given input text, going to the next word every time it's called.
function displayText() {
var text = document.getElementById("words").value;
// Since text is initialized
// every time the method is called,
// it will always start at the beginning of the text area.
// Not sure how to fix this since making `text`
// a global variable doesn't work
var list = text.split(/[ \t\n]+/);
displayNext(list, "display");
}
There is a "helper" method, displayNext, which is supposed to shift to the next word in the list and sets the display to that word.
function displayNext(list, textboxID) {
document.getElementById(textboxID).innerHTML = list.shift();
}
This isn't working as it is intended. I'm fairly sure it's because I've mucked up something with the parameters, since displayNext sets innerHTML to null. list must have not passed properly. I'm not sure how to fix this.
I'm sure there's a more efficient way to do this, but this is a good opportunity to learn how Javascript parameters actually work, so I thought I'd ask.
JSFiddle
Based on the comments in your code, it sounds like you want displayText() to display the "next" word each time. To do that, you have to create some place to store some state about which word is the next one to display. As you have it now, you create a new array every time and always display the first word.
The simplest way is to create a variable outside your function in some lasting scope where you store the word number:
var wordNum = 0;
function displayText() {
var text = document.getElementById("words").value;
var list = text.split(/\s+/);
if (list.length !== 0) {
// make sure we aren't off the end of the list
wordNum = wordNum % list.length;
displayNext(list[wordNum++], "display");
}
}
function displayNext(text, textboxID) {
document.getElementById(textboxID).innerHTML = text;
}
For a lot more info about arguments to Javascript functions and even how you can detect what arguments were passed or overload arguments, see this answer: How to overload functions in javascript? and for more info about how arguments are passed: Javascript by reference vs. by value

how to get the total number of unique fucntions in a JS script

I am looking at the source of pace.js and it has a pretty long source code of about a thousand lines. You can view the source here.
I need to debug this code. Is there any tool or method in JavaScript using which one can identify how many unique functions are there in a given plugin? I found one way which is:
Paste the code in a text editor
Identify each function individually
Paste a console.log("i am so and so function").
Run the script and copy paste the result from the console in a text editor
Count the number of functions
Is there a easier way to do this?
This approach first finds all the functions in the window object. Then passes those function references to 'getInnerFunction()' which matches the function against a regular expression to detect any inner functions. Finally the count of functions is returned.
However it will not be able to detect inner functions of native function present in the browser, since they return
function FUNCTION NAME {
[native code]
}
this as the to string output.
For other cases this should work. Just call fnCount() and you will receive the number of functions present (subtract 2 from the result to exclude these 2 functions).
** Please correct me if there is any problem with the function matching regular expression.
function fnCount(){
var keys = Object.keys(window);
var property;
var count = 0;
for(var i=0;i<keys.length; i++){
property = window[keys[i]];
if(typeof(property) === 'function'){
count += getInnerFunction(property);
}
}
return count;
}
function getInnerFunction(property){
var fn = property.toString();
var fnCount = fn.match(/function.*\(.*\).*{.*/g).length;
return fnCount;
}
Open notepad++, press CTRL+F, type function, click Find all...

Programming optional ignorance

In Javascript what is the best way to handle scenarios when you have a set of arrays to perform tasks on sets of data and sometimes you do not want to include all of the arrays but instead a combination.
My arrays are labeled in this small snippet L,C,H,V,B,A,S and to put things into perspective the code is around 2500 lines like this. (I have removed code notes from this post)
if(C[0].length>0){
L=L[1].concat(+(MIN.apply(this,L[0])).toFixed(7));
C=C[1].concat(C[0][0]);
H=H[1].concat(+(MAX.apply(this,H[0])).toFixed(7));
V=V[1].concat((V[0].reduce(function(a,b){return a+b}))/(V[0].length));
B=B[1].concat((MAX.apply(this,B[0])-MIN.apply(this,B[0]))/2);
A=A[1].concat((MAX.apply(this,A[0])-MIN.apply(this,A[0]))/2);
D=D[1].concat((D[0].reduce(function(a,b){return a+b}))/(D[0].length));
S=S[1].concat((S[0].reduce(function(a,b){return a+b}))/(S[0].length));
}
It would seem counter-productive in this case to litter the code with tones of bool conditions asking on each loop or code section if an array was included in the task and even more silly to ask inside each loop iteration with say an inline condition as these would also slow down the processing and also make the code look like a maze or rabbit hole.
Is there a logical method / library to ignore instruction or skip if an option was set to false
All I have come up with so far is kind of pointless inline thing
var op=[0,1,1,0,0,0,0,0]; //options
var L=[],C=[],H=[],V=[],B=[],A=[],D=[],S=[];
op[0]&&[L[0]=1];
op[1]&&[C[0]=1,console.log('test, do more than one thing')];
op[2]&&[H[0]=1];
op[3]&&[V[0]=1];
op[4]&&[B[0]=1];
op[5]&&[A[0]=1];
op[6]&&[A[0]=1];
It works in that it sets only C[0] and H[0] to 1 as the options require, but it fails as it needs to ask seven questions per iteration of a loop as it may be done inside a loop. Rather than make seven versions of the the loop or code section, and rather than asking questions inside each loop is there another style / method?
I have also noticed that if I create an array then at some point make it equal to NaN rather than undefined or null the console does not complain
var L=[],C=[],H=[],V=[],B=[],A=[],D=[],S=[];
L=NaN;
L[0]=1;
//1
console.log(L); //NaN
L=undefined;
L[0]=1
//TypeError: Cannot set property '0' of undefined
L=null
L[0]=1
//TypeError: Cannot set property '0' of null
Am I getting warmer? I would assume that if I performed some math on L[0] when isNaN(L)===true that the math is being done but not stored so the line isn't being ignored really..
If I understand what you want I would do something like this.
var op = [...],
opchoice = {
//these can return nothing, no operation, or a new value.
'true': function(val){ /*operation do if true*/ },
'false': function(val){ /*operation do if false*/ },
//add more operations here.
//keys must be strings, or transformed into strings with operation method.
operation: function(val){
//make the boolean a string key.
return this[''+(val == 'something')](val);
}
};
var endop = [];//need this to prevent infinite recursion(loop).
var val;
while(val = op.shift()){
//a queue operation.
endop.push(opchoice.operation(val));
}
I'm sure this is not exactly what you want, but it's close to fulfilling the want of not having a ton of conditions every where.
Your other option is on every line do this.
A = isNaN(A) ? A.concat(...) : A;
Personally I prefer the other method.
It looks like you repeat many of the operations. These operations should be functions so at least you do not redefine the same function over and over again (it is also an optimization to do so).
function get_min(x)
{
return +(MIN.apply(this, a[0])).toFixed(7);
}
function get_max(x)
{
return +(MAX.apply(this, a[0])).toFixed(7);
}
function get_average(x)
{
return (x[0].reduce(function(a, b) {return a + b})) / (x[0].length);
}
function get_mean(x)
{
return (MAX.apply(this, x[0]) - MIN.apply(this, x[0])) / 2;
}
if(C[0].length > 0)
{
L = L[1].concat(get_min(L));
C = C[1].concat(C[0][0]);
H = H[1].concat(get_max(H));
V = V[1].concat(get_average(V));
B = B[1].concat(get_mean(B));
A = A[1].concat(get_mean(A);
D = D[1].concat(get_average(D));
S = S[1].concat(get_average(S));
}
You could also define an object with prototype functions, but it is not clear whether it would be useful (outside of putting those functions in a namespace).
In regard to the idea/concept of having a test, what you've found is probably the best way in JavaScript.
op[0] && S = S[1].concat(get_average(S));
And if you want to apply multiple operators when op[0] is true, use parenthesis and commas:
op[3] && (V = V[1].concat(get_average(V)),
B = B[1].concat(get_mean(B)),
A = A[1].concat(get_mean(A));
op[0] && (D = D[1].concat(get_average(D)),
S = S[1].concat(get_average(S)));
However, this is not any clearer, to a programmer, than an if() block as shown in your question. (Actually, many programmers may have to read it 2 or 3 times before getting it.)
Yet, there is another solution which is to use another function layer. In that last example, you would do something like this:
function VBA()
{
V = V[1].concat(get_average(V));
B = B[1].concat(get_mean(B));
A = A[1].concat(get_mean(A));
}
function DS()
{
D = D[1].concat(get_average(D));
S = S[1].concat(get_average(S));
}
op = [DS,null,null,VBA,null,null,...];
for(key in op)
{
// optional: if(op[key].hasOwnProperty(key)) ... -- verify that we defined that key
if(op[key])
{
op[key](); // call function
}
}
So in other words you have an array of functions and can use a for() loop to go through the various items and if defined, call the function.
All of that will very much depend on the number of combinations you have. You mentioned 2,500 lines of code, but the number of permutations may be such that writing it one way or the other will possibly not reduce the total number of lines, but it will make it easier to maintain because many lines are moved to much smaller code snippet making the overall program easier to understand.
P.S. To make it easier to read and debug later, I strongly suggest you put more spaces everywhere, as shown above. If you want to save space, use a compressor (minimizer), Google or Yahoo! both have one that do a really good job. No need to write your code pre-compressed.

How to write a generic function that passes one argument to then function then called multiple times

I have been stuck on this homework:
Create a generic function that outputs one line of the countdown on
the web page, followed by an alert, and receives the data to output as
an input parameter.
Use that function to output each line of the countdown, and an alert.
Please note that you are outputting the countdown to the browser
window this time, not to an alert!
The alert is only being used to signal when to output the next line
I need help in how to come up with a generic function that passes only one argument and then can be called 13 times. To write a for loop that output the numeric part of a countdown.
I think the key here is that they're asking for "Generic".
That means one function that doesn't have to know anything but what it's doing.
It also usually means that it shouldn't remember anything about what it did last time, or what it's going to do next time it's called (unless you're writing a generic structure specifically for remembering).
Now, the wording of the specification is poor, but a generic function which:
takes (input) data to write
writes the input to the page
calls an alert
is much simpler than you might think.
var writeInputAndAlert = function (input) {
// never, ever, ***ever*** use .write / .writeLn in the real world
document.writeLn(input);
window.alert("next");
};
If I was your teacher, I would then rewrite window.alert to handle the non-generic portion.
It's non-generic, because it knows the rules of the program, and it remembers where you are, and where you're going.
var countFrom = 100,
currentCount = countFrom,
countTo = 0;
var nextCount = function () {
currentCount -= 1;
if (currentCount >= countTo) { writeInputAndAlert(currentCount); }
};
window.alert = nextCount;
edit
var countdownArray = ["ten", "nine", "eight", "Ignition Start", "Lift Off", "We have Lift Off"],
i = 0, end = countdownArray.length, text = "",
printAndAlert = function (item) {
alert();
document.write(item);
};
for (; i < end; i += 1) {
text = countdownArray[i];
printAndAlert(text);
}
This really doesn't need to be any harder than that.
printAndAlert is a generic function that takes one input, writes that input and triggers an alert.
You call it inside of a for loop, with each value in your array.
That's all there is to it.
If I understand correctly, you want to create a function that will allow you to pass the data once, and then you can call that function to output the data line by line.
To do this exactly that way isn't possible, but this method is almost the same:
function createOutputFunction(dataArray)
{
return function() {
document.write(dataArray.shift()); // This writes the first element of the dataArray to the browser
};
}
//It can then be used like this
outputFunction = createOutputFunction(["Banana", "Mango", "Apple"]);
outputFunction();
outputFunction();
outputFunction();
The "createOutputFunction" function returns a function that can read the "dataArray" variable and print its first element every time it is called.

sequential calls of methods asynchronously

I have a list of methods I am calling in a method, as follows:
this.doOneThing();
someOtherObject.doASecondThing();
this.doSomethingElse();
When this is synchronous, they are executed one after the other, which is required. But now I have someOtherObject.doASecondThing() as asynchronous, and I might turn doOneThing as async too. I could use a callback and call that.doSomethingElse from inside the callback:
var that = this;
this.doOneThing( function () {
someOtherObject.doASecondThing(function () {
that.doSomethingElse();
});
});
However, because the sequence is growing, it seems a little messy to have callbacks call each other, for some reason it makes the sequence not look as obvious as before, and the indentation might grow with the number of methods called in the sequence.
Is there a way to make this look better? I could use the observer pattern also but it doesn't make things very obvious either, in my opinion.
Thanks,
Continuations, and why they're causing callback spaghetti
Writing in callbacks forces you to write in sometime akin to "continuation-passing style" (CPS), an extremely powerful but difficult technique. It represents a total inversion of control, literally turning a computation "upside-down". CPS makes your code's structure explicitly reflect the control flow of your program (sometimes a good thing, sometimes a bad thing). In effect, you are explicitly writing down the stack out of anonymous functions.
As a prerequisite for understanding this answer, you may find this useful:
http://matt.might.net/articles/by-example-continuation-passing-style/
For example this is what you are doing:
function thrice(x, ret) {
ret(x*3)
}
function twice(y, ret) {
ret(y*2)
}
function plus(x,y, ret) {
ret(x+y)
}
function threeXPlusTwoY(x,y, ret) {
// STEP#1
thrice(x, // Take the result of thrice(x)...
function(r1) { // ...and call that r1.
// STEP#2
twice(y, // Take the result of twice(y)...
function(r2) { // ...and call that r2.
// STEP#3
plus(r1,r2, // Take r1+r2...
ret // ...then do what we were going to do.
)
}
)
}
)
}
threeXPlusTwoY(5,1, alert); //17
As you've complained about, this makes for fairly indented code, because closures are the natural way to capture this stack.
Monads to the rescue
One way to unindent CPS is to write "monadically" like in Haskell. How would we do that? One nice way of implementing monads in javascript is with the dot-chaining notation, similar to jQuery. (See http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/ for an amusing diversion.) Or we can use reflection.
But first we need a way to "write down the plumbing", and THEN we can find a way abstract it away. Tragically it's sort of hard to write a generic monad syntax in javascript, so I will use lists to represent computations.
// switching this up a bit:
// it's now 3x+2x so we have a diamond-shaped dependency graph
// OUR NEW CODE
var _x = 0;
var steps = [
[0, function(ret){ret(5)},[]], //step0:
[1, thrice,[_x]], //step1: thrice(x)
[2, twice,[_x]], //step2: twice(x)
[3, plus,[1, 2]] //step3: steps[1]+steps[2] *
]
threeXPlusTwoX = generateComputation(steps);
//*this may be left ambiguous, but in this case we will choose steps1 then step2
// via the order in the array
That's kinda ugly. But we can make this UNINDENTED "code" work. We can worry about making it prettier later (in the last section). Here our purpose was to write down all the "necessary information". We'd like an easy way to write each "line", along with a context we can write them in.
Now we implement a generateComputation which generates some nested anonymous functions which would perform the above steps in-order if we executed it. This is what such an implementation would look like:
function generateComputation(steps) {
/*
* Convert {{steps}} object into a function(ret),
* which when called will perform the steps in order.
* This function will call ret(_) on the results of the last step.
*/
function computation(ret) {
var stepResults = [];
var nestedFunctions = steps.reduceRight(
function(laterFuture, step) {
var i = step[0]; // e.g. step #3
var stepFunction = step[1]; // e.g. func: plus
var stepArgs = step[2]; // e.g. args: 1,2
console.log(i, laterFuture);
return function(returned) {
if (i>0)
stepResults.push(returned);
var evalledStepArgs = stepArgs.map(function(s){return stepResults[s]});
console.log({i:i, returned:returned, stepResults:stepResults, evalledStepArgs:evalledStepArgs, stepFunction:stepFunction});
stepFunction.apply(this, evalledStepArgs.concat(laterFuture));
}
},
ret
);
nestedFunctions();
}
return computation;
}
Demonstration:
threeXPlusTwoX = generateComputation(steps)(alert); // alerts 25
sidenote: reduceRight semantics implies the steps on the right will be more deeply nested in functions (further in the future). FYI for those not familiar, [1,2,3].reduce(f(_,_), x) --> f(f(f(0,1), 2), 3), and reduceRight (due to poor design considerations) is actually equivalent to [1.2.3].reversed().reduce(...)
Above, generateComputation made a bunch of nested functions, wrapping them in one another in preparation, and when evaluated with ...(alert), unpeeled them one-by-one to feed into the computation.
sidenote: We have to use a hack because in the previous example, we used closures and variable names to implement CPS. Javascript does not allow sufficient reflection to do this without resorting to crafting a string and evaling it (ick), so we eschew functional style temporarily and opt for mutating an object that keeps track of all parameters. Thus the above more closely replicates the following:
var x = 5;
function _x(ret) {
ret(x);
}
function thrice(x, ret) {
ret(x*3)
}
function twice(y, ret) {
ret(y*2)
}
function plus(x,y, ret) {
ret(x+y)
}
function threeXPlusTwoY(x,y, ret) {
results = []
_x(
return function(x) {
results[0] = x;
thrice(x, // Take the result of thrice(x)...
function(r1) { // ...and call that r1.
results[1] = r1;
twice(y, // Take the result of twice(y)...
function(r2) { // ...and call that r2.
results[2] = r2;
plus(results[1],results[2], // Take r1+r2...
ret // ...then do what we were going to do.
)
}
)
}
)
}
)
}
Ideal syntax
But we still want to write functions in a sane way. How would we ideally like to write our code to take advantage of CPS, but while retaining our sanity? There are numerous takes in the literature (for example, Scala's shift and reset operators are just one of the many ways to do so), but for sanity's sake, let's just find a way to make syntactic sugar for regular CPS. There are some possible ways to do it:
// "bad"
var _x = 0;
var steps = [
[0, function(ret){ret(5)},[]], //step0:
[1, thrice,[_x]], //step1: thrice(x)
[2, twice,[_x]], //step2: twice(x)
[3, plus,[1, 2]] //step3: steps[1]+steps[2] *
]
threeXPlusTwoX = generateComputation(steps);
...becomes...
If the callbacks are in a chain, we can easily feed one into the next without worrying about naming. These functions only have one argument: the callback argument. (If they didn't, you could curry the function as follows on the last line.) Here we can use jQuery-style dot-chains.
// SYNTAX WITH A SIMPLE CHAIN
// ((2*X) + 2)
twiceXPlusTwo = callbackChain()
.then(prompt)
.then(twice)
.then(function(returned){return plus(returned,2)}); //curried
twiceXPlusTwo(alert);
If the callbacks form a dependency tree, we can also get away with jQuery-style dot-chains, but this would defeat the purpose of creating a monadic syntax for CPS, which is to flatten the nested functions. Thus we won't go into detail here.
If the callbacks form a dependency acyclic graph (for example, 2*x+3*x, where x is used twice) we would need a way to name the intermediate results of some callbacks. This is where it gets interesting. Our goal is to try to mimic the syntax at http://en.wikibooks.org/wiki/Haskell/Continuation_passing_style with its do-notation which "unwraps" and "rewraps" functions into and out of CPS. Unfortunately the [1, thrice,[_x]] syntax was the closest we could easily get to that (and not even close). You could code in another language and compile to javascript, or using eval (queue the ominous music). A bit overkill. Alternatives would have to use strings, such as:
// SUPER-NICE SYNTAX
// (3X + 2X)
thriceXPlusTwiceX = CPS({
leftPart: thrice('x'),
rightPart: twice('x'),
result: plus('leftPart', 'rightPart')
})
You can do this with only a few tweaks to the generateComputation I described. First you adapt it to use logical names ('leftPart', etc.) rather than numbers. Then you make your functions actually lazy objects which behave like:
thrice(x).toListForm() == [<real thrice function>, ['x']]
or
thrice(x).toCPS()(5, alert) // alerts 15
or
thrice.toNonCPS()(5) == 15
(You would do this in an automated way with some kind of decorator, not manually.)
sidenote: All your callback functions should follow the same protocol about where the callback parameter is. For example if your functions begin with myFunction(callback, arg0, arg1, ...) or myFunction(arg0, arg1, ..., callback) they might not be trivially compatible, though if they aren't presumably you could do a javascript reflection hack to look at the source code of the function and regex it out, and thus not have to worry about it.
Why go through all that trouble? This allows you to mix in setTimeouts and prompts and ajax requests without suffering from "indent hell". You also get a whole bunch of other benefits (like being able to write a 10-line nondeterministic-search sudoku solver, and implementing arbitrary control-flow operators) which I will not go into here.

Categories

Resources