Related
In https://tc39.es/ecma262/#sec-algorithm-conventions-syntax-directed-operations, There is a description like this
Syntax-directed operations are invoked with a parse node and, optionally, other parameters by using the conventions on steps 1, 3, and 4 in the following algorithm:
Let status be SyntaxDirectedOperation of SomeNonTerminal.
Let someParseNode be the parse of some source text.
Perform SyntaxDirectedOperation of someParseNode.
Perform SyntaxDirectedOperation of someParseNode with argument "value".
What does status in this algorithm mean? It's not used in the algorithm anymore.
What does the algorithm mean? It seems weird.
That's just an example, it's not a real algorithm, and it's not necessarily a complete example (hence not using status after the first step). For a real algorithm, look at the section containing actual Syntax-Directed Operations, such as function name inference:
8.4.1 Static Semantics: HasName
...
Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
If IsFunctionDefinition of expr is false, return false.
Return HasName of expr.
The status in the example is like expr in the above, a temporary variable (if you will) for the algorithm. It's just that the example doesn't use status again (it probably should, it would be a better example).
What does status in this algorithm mean?
It's just a variable introduced by that step, like in any other "Let x be …".
What does the algorithm mean? It seems weird.
It means nothing. It's an example algorithm in the "algorithm conventions" section explaining how algorithm steps are meant to be understood in the rest of the spec.
What is the name of the native function that handles template literals?
That is, I know that when you write tag`Foo ${'bar'}.`;, that’s just syntactic sugar for tag(['Foo ', '.'], 'bar');.¹
But what about just `Foo ${'bar'}.`;? I can’t just “call” (['Foo ', '.'], 'bar');. If I already have arguments in that form, what function should I pass them to?
I am only interested in the native function that implements the template literal functionality. I am quite capable of rolling my own, but the purpose of this question is to avoid that and do it “properly”—even if my implementation is a perfect match of current native functionality, the native functionality can change and I want my usage to still match. So answers to this question should take on one of the following forms:
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
A backed-up statement that the native implementation is unavailable and unspecified. Ideally this is backed up by, again, links to and/or quotes from documentation, but if that’s unavailable, I’ll accept other sources or argumentation that backs this claim up.
Actually, the first argument needs a raw property, since it’s a TemplateStringsArray rather than a regular array, but I’m skipping that here for the sake of making the example more readable.
Motivation
I am trying to create a tag function (tag, say) that, internally, performs the default template literal concatenation on the input. That is, I am taking the TemplateStringsArray and the remaining arguments, and turning them into a single string that has already had its templating sorted out. (This is for passing the result into another tag function, otherTag perhaps, where I want the second function to treat everything as a single string literal rather than a broken up template.)
For example, tag`Something ${'cooked'}.`; would be equivalent to otherTag`Something cooked.`;.
My current approach
The definition of tag would look something like this:
function tag(textParts, ...expressions) {
const cooked = // an array with a single string value
const raw = // an array with a single string value
return otherTag({ ...cooked, raw });
}
Defining the value of raw is fairly straightforward: I know that String.raw is the tag function I need to call here, so const raw = [String.raw(textParts.raw, ...expressions)];.
But I cannot find anywhere on the internet what function I would call for the cooked part of it. What I want is, if I have tag`Something ${'cooked'}.`;, I want const cooked = `Something ${cooked}.`; in my function. But I can’t find the name of whatever function accomplishes that.
The closest I’ve found was a claim that it could be implemented as
const cooked = [expressions.map((exp, i) => textParts[i] + exp).join('')];
This is wrong—textParts may be longer than expressions, since tag`Something ${'cooked'}.`; gets ['Something ', '.'] and ['cooked'] as its arguments.
Improving this expression to handle that isn’t a problem:
const cooked = [
textParts
.map((text, i) => (i > 0 ? expressions[i-1] : '') + text)
.join(''),
];
But that’s not the point—I don’t want to roll my own here and risk it being inconsistent with the native implementation, particularly if that changes.
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
There isn't one. It is syntax, not a function.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
Section 13.2.8 Template Literals of the specification explains how to process the syntax.
Intro
This topic has been the bane of many questions and answers on StackOverflow -and in many other tech-forums; however, most of them are specific to exact conditions and even worse: "over-all" security in script-injection prevention via dev-tools-console, or dev-tools-elements or even address-bar is said to be "impossible" to protect. This question is to address these issues and serve as current and historical reference as technology improves -or new/better methods are discovered to address browser security issues -specifically related to script-injection attacks.
Concerns
There are many ways to either extract -or manipulate information "on the fly"; specifically, it's very easy to intercept information gathered from input -to be transmitted to the server - regardless of SSL/TLS.
intercept example
Have a look here
Regardless of how "crude" it is, one can easily use the principle to fabricate a template to just copy+paste into an eval() in the browser console to do all kinds of nasty things such as:
console.log() intercepted information in transit via XHR
manipulate POST-data, changing user-references such as UUIDs
feed the target-server alternative GET (& post) request information to either relay (or gain) info by inspecting the JS-code, cookies and headers
This kind of attack "seems" trivial to the untrained eye, but when highly dynamic interfaces are in concern, then this quickly becomes a nightmare -waiting to be exploited.
We all know "you can't trust the front-end" and the server should be responsible for security; however - what about the privacy/security of our beloved visitors? Many people create "some quick app" in JavaScript and either do not know (or care) about the back-end security.
Securing the front-end as well as the back-end would prove formidable against an average attacker, and also lighten the server-load (in many cases).
Efforts
Both Google and Facebook have implemented some ways of mitigating these issues, and they work; so it is NOT "impossible", however, they are very specific to their respective platforms and to implement requires the use of entire frameworks plus a lot of work -only to cover the basics.
Regardless of how "ugly" some of these protection mechanisms may appear; the goal is to help (mitigate/prevent) security issues to some degree, making it difficult for an attacker. As everybody knows by now: "you cannot keep a hacker out, you can only discourage their efforts".
Tools & Requirements
The goal is to have a simple set of tools (functions):
these MUST be in plain (vanilla) javascript
together they should NOT exceed a few lines of code (at most 200)
they have to be immutable, preventing "re-capture" by an attacker
these MUST NOT clash with any (popular) JS frameworks, such as React, Angular, etc
does NOT have to be "pretty", but readable at least, "one-liners" welcome
cross-browser compatible, at least to a good percentile
Runtime Reflection / Introspection
This is a way to address some of these concerns, and I don't claim it's "the best" way (at all), it's an attempt.
If one could intercept some "exploitable" functions and methods and see if "the call" (per call) was made from the server that spawned it, or not, then this could prove useful as then we can see if the call came "from thin air" (dev-tools).
If this approach is to be taken, then first we need a function that grabs the call-stack and discard that which is not FUBU (for us by us). If the result of this function is empty, hazaa! - we did not make the call and we can proceed accordingly.
a word or two
In order to make this as short & simple as possible, the following code examples follow DRYKIS principles, which are:
don't repeat yourself, keep it simple
"less code" welcomes the adept
"too much code & comments" scare away everybody
if you can read code - go ahead and make it pretty
With that said, pardon my "short-hand", explanation will follow
first we need some constants and our stack-getter
const MAIN = window;
const VOID = (function(){}()); // paranoid
const HOST = `https://${location.host}`; // if not `https` then ... ?
const stak = function(x,a, e,s,r,h,o)
{
a=(a||''); e=(new Error('.')); s=e.stack.split('\n'); s.shift(); r=[]; h=HOSTPURL; o=['_fake_']; s.forEach((i)=>
{
if(i.indexOf(h)<0){return}; let p,c,f,l,q; q=1; p=i.trim().split(h); c=p[0].split('#').join('').split('at ').join('').trim();
c=c.split(' ')[0];if(!c){c='anon'}; o.forEach((y)=>{if(((c.indexOf(y)==0)||(c.indexOf('.'+y)>0))&&(a.indexOf(y)<0)){q=0}}); if(!q){return};
p=p[1].split(' '); f=p[0]; if(f.indexOf(':')>0){p=f.split(':'); f=p[0]}else{p=p.pop().split(':')}; if(f=='/'){return};
l=p[1]; r[r.length]=([c,f,l]).join(' ');
});
if(!isNaN(x*1)){return r[x]}; return r;
};
After cringing, bare in mind this was written "on the fly" as "proof of concept", yet tested and it works. Edit as you whish.
stak() - short explanation
the only 2 relevant arguments are the 1st 2, the rest is because .. laziness (short answer)
both arguments are optional
if the 1st arg x is a number then e.g. stack(0) returns the 1st item in the log, or undefined
if the 2nd arg a is either a string -or an array then e.g. stack(undefined, "anonymous") allows "anonymous" even though it was "omitted" in o
the rest of the code just parses the stack quickly, this should work in both webkit & gecko -based browsers (chrome & firefox)
the result is an array of strings, each string is a log-entry separated by a single space as function file line
if the domain-name is not found in a log-entry (part of filename before parsing) then it won't be in the result
by default it ignores filename / (exactly) so if you test this code, putting in a separate .js file will yield better results than in index.html (typically) -or whichever web-root mechanism is used
don't worry about _fake_ for now, it's in the jack function below
now we need some tools
bore() - get/set/rip some value of an object by string reference
const bore = function(o,k,v)
{
if(((typeof k)!='string')||(k.trim().length<1)){return}; // invalid
if(v===VOID){return (new Function("a",`return a.${k}`))(o)}; // get
if(v===null){(new Function("a",`delete a.${k}`))(o); return true}; // rip
(new Function("a","z",`a.${k}=z`))(o,v); return true; // set
};
bake() - shorthand to harden existing object properties (or define new ones)
const bake = function(o,k,v)
{
if(!o||!o.hasOwnProperty){return}; if(v==VOID){v=o[k]};
let c={enumerable:false,configurable:false,writable:false,value:v};
let r=true; try{Object.defineProperty(o,k,c);}catch(e){r=false};
return r;
};
bake & bore - rundown
These are failry self-explanatory, so, some quick examples should suffice
using bore to get a property: console.log(bore(window,"XMLHttpRequest.prototype.open"))
using bore to set a property: bore(window,"XMLHttpRequest.prototype.open",function(){return "foo"})
using bore to rip (destroy carelessly): bore(window,"XMLHttpRequest.prototype.open",null)
using bake to harden an existing property: bake(XMLHttpRequest.prototype,'open')
using bake to define a new (hard) property: bake(XMLHttpRequest.prototype,'bark',function(){return "woof!"})
intercepting functions and constructions
Now we can use all the above to our advantage as we devise a simple yet effective interceptor, by no means "perfect", but it should suffice; explanation follows:
const jack = function(k,v)
{
if(((typeof k)!='string')||!k.trim()){return}; // invalid reference
if(!!v&&((typeof v)!='function')){return}; // invalid callback func
if(!v){return this[k]}; // return existing definition, or undefined
if(k in this){this[k].list[(this[k].list.length)]=v; return}; //add
let h,n; h=k.split('.'); n=h.pop(); h=h.join('.'); // name & holder
this[k]={func:bore(MAIN,k),list:[v]}; // define new callback object
bore(MAIN,k,null); let f={[`_fake_${k}`]:function()
{
let r,j,a,z,q; j='_fake_'; r=stak(0,j); r=(r||'').split(' ')[0];
if(!r.startsWith(j)&&(r.indexOf(`.${j}`)<0)){fail(`:(`);return};
r=jack((r.split(j).pop())); a=([].slice.call(arguments));
for(let p in r.list)
{
if(!r.list.hasOwnProperty(p)||q){continue}; let i,x;
i=r.list[p].toString(); x=(new Function("y",`return {[y]:${i}}[y];`))(j);
q=x.apply(r,a); if(q==VOID){return}; if(!Array.isArray(q)){q=[q]};
z=r.func.apply(this,q);
};
return z;
}}[`_fake_${k}`];
bake(f,'name',`_fake_${k}`); bake((h?bore(MAIN,h):MAIN),n,f);
try{bore(MAIN,k).prototype=Object.create(this[k].func.prototype)}
catch(e){};
}.bind({});
jack() - explanation
it takes 2 arguments, the first as string (used to bore), the second is used as interceptor (function)
the first few comments explain a bit .. the "add" line simply adds another interceptor to the same reference
jack deposes an existing function, stows it away, then use "interceptor-functions" to replay arguments
the interceptors can either return undefined or a value, if no value is returned from any, the original function is not called
the first value returned by an interceptor is used as argument(s) to call the original and return is result to the caller/invoker
that fail(":(") is intentional; an error will be thrown if you don't have that function - only if the jack() failed.
Examples
Let's prevent eval from being used in the console -or address-bar
jack("eval",function(a){if(stak(0)){return a}; alert("having fun?")});
extensibility
If you want a DRY-er way to interface with jack, the following is tested and works well:
const hijack = function(l,f)
{
if(Array.isArray(l)){l.forEach((i)=>{jack(i,f)});return};
};
Now you can intercept in bulk, like this:
hijack(['eval','XMLHttpRequest.prototype.open'],function()
{if(stak(0)){return ([].slice.call(arguments))}; alert("gotcha!")});
A clever attacker may then use the Elements (dev-tool) to modify an attribute of some element, giving it some onclick event, then our interceptor won't catch that; however, we can use a mutation-observer and with that spy on "attribute changes". Upon attribute-change (or new-node) we can check if changes were made FUBU (or not) with our stak() check:
const watchDog=(new MutationObserver(function(l)
{
if(!stak(0)){alert("you again! :D");return};
}));
watchDog.observe(document.documentElement,{childList:true,subtree:true,attributes:true});
Conclusion
These were but a few ways of dealing with a bad problem; though I hope someone finds this useful, and please feel free to edit this answer, or post more (or alternative/better) ways of improving front-end security.
I don’t think I’ve grokked currying yet. I understand what it does, and how to do it. I just can’t think of a situation I would use it.
Where are you using currying in JavaScript (or where are the main libraries using it)? DOM manipulation or general application development examples welcome.
One of the answers mentions animation. Functions like slideUp, fadeIn take an element as an arguments and are normally a curried function returning the high order function with the default “animation function” built-in. Why is that better than just applying the higher-up function with some defaults?
Are there any drawbacks to using it?
As requested here are some good resources on JavaScript currying:
http://www.dustindiaz.com/javascript-curry/
Crockford, Douglas (2008) JavaScript: The Good Parts
http://www.svendtofte.com/code/curried_javascript/
(Takes a detour into ML so skip the whole section from “A crash course in ML” and start again at “How to write curried JavaScript”)
http://web.archive.org/web/20111217011630/http://blog.morrisjohns.com:80/javascript_closures_for_dummies
How do JavaScript closures work?
http://ejohn.org/blog/partial-functions-in-javascript (Mr. Resig on the money as per usual)
http://benalman.com/news/2010/09/partial-application-in-javascript/
I’ll add more as they crop up in the comments.
So, according to the answers, currying and partial application in general are convenience techniques.
If you are frequently “refining” a high-level function by calling it with same configuration, you can curry (or use Resig’s partial) the higher-level function to create simple, concise helper methods.
Here's an interesting AND practical use of currying in JavaScript that uses closures:
function converter(toUnit, factor, offset, input) {
offset = offset || 0;
return [((offset + input) * factor).toFixed(2), toUnit].join(" ");
}
var milesToKm = converter.curry('km', 1.60936, undefined);
var poundsToKg = converter.curry('kg', 0.45460, undefined);
var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32);
milesToKm(10); // returns "16.09 km"
poundsToKg(2.5); // returns "1.14 kg"
farenheitToCelsius(98); // returns "36.67 degrees C"
This relies on a curry extension of Function, although as you can see it only uses apply (nothing too fancy):
Function.prototype.curry = function() {
if (arguments.length < 1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat([].slice.apply(null, arguments)));
}
}
#Hank Gay
In response to EmbiggensTheMind's comment:
I can't think of an instance where currying—by itself—is useful in JavaScript; it is a technique for converting function calls with multiple arguments into chains of function calls with a single argument for each call, but JavaScript supports multiple arguments in a single function call.
In JavaScript—and I assume most other actual languages (not lambda calculus)—it is commonly associated with partial application, though. John Resig explains it better, but the gist is that have some logic that will be applied to two or more arguments, and you only know the value(s) for some of those arguments.
You can use partial application/currying to fix those known values and return a function that only accepts the unknowns, to be invoked later when you actually have the values you wish to pass. This provides a nifty way to avoid repeating yourself when you would have been calling the same JavaScript built-ins over and over with all the same values but one. To steal John's example:
String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );
Agreeing with Hank Gay - It's extremely useful in certain true functional programming languages - because it's a necessary part. For example, in Haskell you simply cannot take multiple parameters to a function - you cannot do that in pure functional programming. You take one param at a time and build up your function. In JavaScript it's simply unnecessary, despite contrived examples like "converter". Here's that same converter code, without the need for currying:
var converter = function(ratio, symbol, input) {
return (input*ratio).toFixed(2) + " " + symbol;
}
var kilosToPoundsRatio = 2.2;
var litersToUKPintsRatio = 1.75;
var litersToUSPintsRatio = 1.98;
var milesToKilometersRatio = 1.62;
converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs
converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints
converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints
converter(milesToKilometersRatio, "km", 34); //55.08 km
I badly wish Douglas Crockford, in "JavaScript: The Good Parts", had given some mention of the history and actual use of currying rather than his offhanded remarks. For the longest time after reading that, I was boggled, until I was studying Functional programming and realized that's where it came from.
After some more thinking, I posit there is one valid use case for currying in JavaScript: if you are trying to write using pure functional programming techniques using JavaScript. Seems like a rare use case though.
I found functions that resemble python's functools.partial more useful in JavaScript:
function partial(fn) {
return partialWithScope.apply(this,
Array.prototype.concat.apply([fn, this],
Array.prototype.slice.call(arguments, 1)));
}
function partialWithScope(fn, scope) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
};
}
Why would you want to use it? A common situation where you want to use this is when you want to bind this in a function to a value:
var callback = partialWithScope(Object.function, obj);
Now when callback is called, this points to obj. This is useful in event situations or to save some space because it usually makes code shorter.
Currying is similar to partial with the difference that the function the currying returns just accepts one argument (as far as I understand that).
Consider filter function. And you want to write a callback for it.
let x = [1,2,3,4,5,6,7,11,12,14,15];
let results = x.filter(callback);
Assume want to output only even numbers, so:
let callback = x => x % 2 === 0;
Now imagine we want to implement our callback such that
depending on scenario it outputs even numbers which are above some threshold number (such
number should be configurable).
We can't easily make such threshold number a parameter to callback function, because filter invokes callback and by default passes it array elements and index.
How would you implement this?
This is a good use case for currying:
let x = [1,2,3,4,5,6,7,11,12,14,15];
let callback = (threshold) => (x) => (x % 2==0 && x > threshold);
let results1 = x.filter(callback(5)); // Even numbers higher than 5
let results2 = x.filter(callback(10)); // Even numbers higher than 10
console.log(results1,results2);
I know its old thread but I will have to show how this is being used in javascript libraries:
I will use lodash.js library to describe these concepts concretely.
Example:
var fn = function(a,b,c){
return a+b+c+(this.greet || ‘');
}
Partial Application:
var partialFnA = _.partial(fn, 1,3);
Currying:
var curriedFn = _.curry(fn);
Binding:
var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}
usage:
curriedFn(1)(3)(5); // gives 9
or
curriedFn(1,3)(5); // gives 9
or
curriedFn(1)(_,3)(2); //gives 9
partialFnA(5); //gives 9
boundFn(5); //gives 9!
difference:
after currying we get a new function with no parameters pre bound.
after partial application we get a function which is bound with some parameters prebound.
in binding we can bind a context which will be used to replace ‘this’, if not bound default of any function will be window scope.
Advise: There is no need to reinvent the wheel. Partial application/binding/currying are very much related. You can see the difference above. Use this meaning anywhere and people will recognise what you are doing without issues in understanding plus you will have to use less code.
It's no magic or anything... just a pleasant shorthand for anonymous functions.
partial(alert, "FOO!") is equivalent to function(){alert("FOO!");}
partial(Math.max, 0) corresponds to function(x){return Math.max(0, x);}
The calls to partial (MochiKit terminology. I think some other libraries give functions a .curry method which does the same thing) look slightly nicer and less noisy than the anonymous functions.
As for libraries using it, there's always Functional.
When is it useful in JS? Probably the same times it is useful in other modern languages, but the only time I can see myself using it is in conjunction with partial application.
I would say that, most probably, all the animation library in JS are using currying. Rather than having to pass for each call a set of impacted elements and a function, describing how the element should behave, to a higher order function that will ensure all the timing stuff, its generally easier for the customer to release, as public API some function like "slideUp", "fadeIn" that takes only elements as arguments, and that are just some curried function returning the high order function with the default "animation function" built-in.
Here's an example.
I'm instrumenting a bunch of fields with JQuery so I can see what users are up to. The code looks like this:
$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);
(For non-JQuery users, I'm saying that any time a couple of fields get or lose focus, I want the trackActivity() function to be called. I could also use an anonymous function, but I'd have to duplicate it 4 times, so I pulled it out and named it.)
Now it turns out that one of those fields needs to be handled differently. I'd like to be able to pass a parameter in on one of those calls to be passed along to our tracking infrastructure. With currying, I can.
JavaScript functions is called lamda in other functional language. It can be used to compose a new api (more powerful or complext function) to based on another developer's simple input. Curry is just one of the techniques. You can use it to create a simplified api to call a complex api. If you are the develper who use the simplified api (for example you use jQuery to do simple manipulation), you don't need to use curry. But if you want to create the simplified api, curry is your friend. You have to write a javascript framework (like jQuery, mootools) or library, then you can appreciate its power. I wrote a enhanced curry function, at http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html . You don't need to the curry method to do currying, it just help to do currying, but you can always do it manually by writing a function A(){} to return another function B(){}. To make it more interesting, use function B() to return another function C().
I agree that at times you would like to get the ball rolling by creating a pseudo-function that will always have the value of the first argument filled in. Fortunately, I came across a brand new JavaScript library called jPaq (http://jpaq.org/) which provides this functionality. The best thing about the library is the fact that you can download your own build which contains only the code that you will need.
Just wanted to add some resources for Functional.js:
Lecture/conference explaining some applications
http://www.youtube.com/watch?v=HAcN3JyQoyY
Updated Functional.js library:
https://github.com/loop-recur/FunctionalJS
Some nice helpers (sorry new here, no reputation :p):
/loop-recur/PreludeJS
I've been using this library a lot recently to reduce the repetition in an js IRC clients helper library. It's great stuff - really helps clean up and simplify code.
In addition, if performance becomes an issue (but this lib is pretty light), it's easy to just rewrite using a native function.
You can use native bind for quick, one line solution
function clampAngle(min, max, angle) {
var result, delta;
delta = max - min;
result = (angle - min) % delta;
if (result < 0) {
result += delta;
}
return min + result;
};
var clamp0To360 = clampAngle.bind(null, 0, 360);
console.log(clamp0To360(405)) // 45
Another stab at it, from working with promises.
(Disclaimer: JS noob, coming from the Python world. Even there, currying is not used all that much, but it can come in handy on occasion. So I cribbed the currying function - see links)
First, I am starting with an ajax call. I have some specific processing to do on success, but on failure, I just want to give the user the feedback that calling something resulted in some error. In my actual code, I display the error feedback in a bootstrap panel, but am just using logging here.
I've modified my live url to make this fail.
function ajax_batch(e){
var url = $(e.target).data("url");
//induce error
url = "x" + url;
var promise_details = $.ajax(
url,
{
headers: { Accept : "application/json" },
// accepts : "application/json",
beforeSend: function (request) {
if (!this.crossDomain) {
request.setRequestHeader("X-CSRFToken", csrf_token);
}
},
dataType : "json",
type : "POST"}
);
promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}
Now, here in order to tell the user that a batch failed, I need to write that info in the error handler, because all it is getting is a response from the server.
I still only have the info available at coding time - in my case I have a number of possible batches, but I don't know which one has failed w.o. parsing the server response about the failed url.
function fail_status_specific_to_batch(d){
console.log("bad batch run, dude");
console.log("response.status:" + d.status);
}
Let's do it. Console output is:
console:
bad batch run, dude
utility.js (line 109)
response.status:404
Now, let's change things a bit and use a reusable generic failure handler, but also one that is curried at runtime with both the known-at-code-time calling context and the run-time info available from event.
... rest is as before...
var target = $(e.target).text();
var context = {"user_msg": "bad batch run, dude. you were calling :" + target};
var contexted_fail_notification = curry(generic_fail, context);
promise_details.then(notify_batch_success, contexted_fail_notification);
}
function generic_fail(context, d){
console.log(context);
console.log("response.status:" + d.status);
}
function curry(fn) {
var slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function () {
var new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
};
}
console:
Object { user_msg="bad batch run, dude. you were calling :Run ACL now"}
utility.js (line 117)
response.status:404
utility.js (line 118)
More generally, given how widespread callback usage is in JS, currying seems like a quite useful tool to have.
https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/
http://www.drdobbs.com/open-source/currying-and-partial-functions-in-javasc/231001821?pgno=2
I asked a similar question at https://softwareengineering.stackexchange.com/questions/384529/a-real-life-example-of-using-curry-function
But only after I use ramda do I finally appreciate the usefulness of curry. So I will argue that if we need to chain functions together to process some input data one step a time, e.g. the promise chain example in the article Favoring Curry, using curry by "function first,data last", the code does look clean!
Here you have a practical example of were currying is being used at the moment.
https://www.joshwcomeau.com/react/demystifying-styled-components/
Basically he is creating a poor man styled components and uses currying to "preload" the name of the tag when creating a new style for it.
Unlike other "FRP" libraries, Rx doesn't prevent glitches: callbacks invoked with time-mismatched data. Is there a good way to work around this?
As an example, imagine that we have a series of expensive computations derived from a single stream (e.g. instead of _.identity, below, we do a sort, or an ajax fetch). We do distinctUntilChanged to avoid recomputing the expensive things.
sub = new Rx.Subject();
a = sub.distinctUntilChanged().share();
b = a.select(_.identity).distinctUntilChanged().share();
c = b.select(_.identity).distinctUntilChanged();
d = Rx.Observable.combineLatest(a, b, c, function () { return _.toArray(arguments); });
d.subscribe(console.log.bind(console));
sub.onNext('a');
sub.onNext('b');
The second event will end up causing a number of glitchy states: we get three events out, instead of one, which wastes a bunch of cpu and requires us to explicitly work around the mismatched data.
This particular example can be worked around by dropping the distinctUntilChanged, and writing some wonky scan() functions to pass through the previous result if the input hasn't changed. Then you can zip the results, instead of using combineLatest. It's clumsy, but doable.
However if there is asynchrony anywhere, e.g. an ajax call, then zip doesn't work: the ajax call will complete either synchronously (if cached) or asynchronously, so you can't use zip.
Edit
Trying to clarify the desired behavior with a simpler example:
You have two streams, a and b. b depends on a. b is asynchronous, but the browser may cache it, so it can either update independently of a, or at the same time as a. So, a particular event in the browser can cause one of three things: a updates; b updates; both a and b update. The desired behavior is to have a callback (e.g. render method) invoked exactly once in all three cases.
zip does not work, because when a or b fires alone, we get no callback from zip. combineLatest does not work because when a and b fire together we get two callbacks.
The concept
both a and b update
where both a and b are observables, doesn't exist as a primitive in Rx.
There is no lossless, general operator that can be defined to decide when it receives a notification from a whether it should pass it downstream or hold off until it receives a notification from b. Notifications in Rx do not natively carry "both" semantics, or any semantics beyond the Rx Grammar for that matter.
Furthermore, Rx's serial contract prevents an operator from taking advantage of overlapping notifications in an attempt to achieve this goal. (Though I suspect that relying on race conditions isn't your desired approach anyway.)
See §§4.2, 6.7 in the Rx Design Guidelines.
Thus, what I meant above by "There is no lossless, general operator that can be defined..." is that given two observables a and b with independent notifications, any operator that attempts to decide when it receives a notification from a or b whether it must push immediately or wait for the "other" value, must rely on arbitrary timings. It's guesswork. So this hypothetical operator must either drop values (e.g., DistinctUntilChanged or Throttle), or drop time (e.g., Zip or Buffer), though probably some combination of both.
Therefore, if the agent has the ability to push a alone, or b alone, or a and b together as a notification unit, then it's the developer's responsibility to reify this concept of notification unit themselves.
A 3-state type is required: a | b | {a,b}
(Please excuse my lousy JS)
var ab = function(a, b) { this.a = a; this.b = b; }
sub.onNext(new ab('a')); // process a alone
sub.onNext(new ab('a', 'b')); // process a and b together
sub.onNext(new ab(null, 'c')); // process c alone
The shape of the observable's query no longer matters. Observers must be defined to accept this data type. It's the generator's responsibility to apply any necessary buffering or timing calculations based on the semantics of its internal state in order to produce correct notifications for its observers.
By the way, thank you for providing a simple explanation in your edit (it seems clear to me anyway). I had first heard about "glitches" in this Rx forum discussion. As you can see, it was never really concluded. Now I wonder whether that OP's problem was really as simple as this, assuming that I've understood your problem correctly, of course. :-)
Update:
Here's another related discussion, including some more of my thoughts on why Rx is not FRP:
https://social.msdn.microsoft.com/Forums/en-US/bc2c4b71-c97b-428e-ad71-324055a3cd03/another-discussion-on-glitches-and-rx?forum=rx