How to test a function that output is random using Jest? - javascript

How to test a function that output is random using Jest? Like this:
import cuid from 'cuid';
const functionToTest = (value) => ({
[cuid()]: {
a: Math.random(),
b: new Date().toString(),
c: value,
}
});
So the output of functionToTest('Some predictable value') will be something like:
{
'cixrchnp60000vhidc9qvd10p': {
a: 0.08715126430943698,
b: 'Tue Jan 10 2017 15:20:58 GMT+0200 (EET)',
c: 'Some predictable value'
},
}

I used:
beforeEach(() => {
jest.spyOn(global.Math, 'random').mockReturnValue(0.123456789);
});
afterEach(() => {
jest.spyOn(global.Math, 'random').mockRestore();
})
It is easy to add and restores the functionality outside the tests.

Here's what I put at the top of my test file:
const mockMath = Object.create(global.Math);
mockMath.random = () => 0.5;
global.Math = mockMath;
In tests run from that file, Math.random always returns 0.5.
Full credit should go to this for the idea: https://stackoverflow.com/a/40460395/2140998, which clarifies that this overwrite is test-specific. My Object.create is just my additional extra little bit of caution avoiding tampering with the internals of Math itself.

I've taken Stuart Watt's solution and ran with it (and got a bit carried away). Stuart's solution is good but I was underwhelmed with the idea of having a random number generator always spit out 0.5 - seems like there would be situations where you're counting on some variance. I also wanted to mock crypto.randomBytes for my password salts (using Jest server-side). I spent a bit of time on this so I figured I'd share the knowledge.
One of the things I noticed is that even if you have a repeatable stream of numbers, introducing a new call to Math.random() could screw up all subsequent calls. I found a way around this problem. This approach should be applicable to pretty much any random thing you need to mock.
(side note: if you want to steal this, you'll need to install Chance.js - yarn/npm add/install chance)
To mock Math.random, put this in one of the files pointed at by your package.json's {"jest":{"setupFiles"} array:
const Chance = require('chance')
const chances = {}
const mockMath = Object.create(Math)
mockMath.random = (seed = 42) => {
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
return chance.random()
}
global.Math = mockMath
You'll notice that Math.random() now has a parameter - a seed. This seed can be a string. What this means is that, while you're writing your code, you can call for the random number generator you want by name. When I added a test to code to check if this worked, I didn't put a seed it. It screwed up my previously mocked Math.random() snapshots. But then when I changed it to Math.random('mathTest'), it created a new generator called "mathTest" and stopped intercepting the sequence from the default one.
I also mocked crypto.randomBytes for my password salts. So when I write the code to generate my salts, I might write crypto.randomBytes(32, 'user sign up salt').toString('base64'). That way I can be pretty sure that no subsequent call to crypto.randomBytes is going to mess with my sequence.
If anyone else is interested in mocking crypto in this way, here's how. Put this code inside <rootDir>/__mocks__/crypto.js:
const crypto = require.requireActual('crypto')
const Chance = require('chance')
const chances = {}
const mockCrypto = Object.create(crypto)
mockCrypto.randomBytes = (size, seed = 42, callback) => {
if (typeof seed === 'function') {
callback = seed
seed = 42
}
chances[seed] = chances[seed] || new Chance(seed)
const chance = chances[seed]
const randomByteArray = chance.n(chance.natural, size, { max: 255 })
const buffer = Buffer.from(randomByteArray)
if (typeof callback === 'function') {
callback(null, buffer)
}
return buffer
}
module.exports = mockCrypto
And then just call jest.mock('crypto') (again, I have it in one of my "setupFiles"). Since I'm releasing it, I went ahead and made it compatible with the callback method (though I have no intention of using it that way).
These two pieces of code pass all 17 of these tests (I created __clearChances__ functions for the beforeEach()s - it just deletes all the keys from the chances hash)
Update: Been using this for a few days now and I think it works pretty well. The only thing is I think that perhaps a better strategy would be creating a Math.useSeed function that's run at the top of tests that require Math.random

I'd ask myself the following questions:
Do I really need to test random output? If I have to, I'd most likely test ranges or make sure that I received a number in a valid format, not the value itself
Is it enough to test the value for c?
Sometimes there is a way to encapsulate the generation of the random value in a Mock and override the generation in your test to return only known values. This is a common practice in my code. How to mock a constructor like new Date() sounds like a similar approach in jestjs.

You could always use jest-mock-random
But it offers a little bit more functionality than mocking it as proposed in the first answer.
For example you could use before the testmockRandomWith(0.6); and your Math.random in test will always return this predictable value

Mocking literal random data isn't exactly the way to test. The question is, as it's stated, is a bit broad because "how to test a function that output is random" requires you to do statistical analysis of the output to ensure effective randomness - which has likely been done by the creators of your pseudo-random number generator.
Inferring instead "that output is random" means you want to ensure the function functions properly regardless of the random data then merely mocking the Math.random call to return numbers that meet your specific criteria (covering any variance) is enough. That function is a third-party boundary that, while needing testing, is not what's being tested based on my inference. Unless it is - in which case refer to the paragraph above.

I agree with Richard Barker answer. Strange that at the time of writing his answer has 0 votes, while the upvoted and accepted ones completely miss the point. Guess this thread is too old.
How to test a function that output is random using Jest? Its not a Jest or even a programming problem, but a statistical (or even philosophical) one and as far as I can understand, mathematics can only conclusively prove that a sequence is non-random, meaning it has a recognizable pattern. Math.random() as all other pseudo-random number generators will eventually put out a pattern, cause they are algorithms.
The best actionable advice is in cringe answer. Test the return range and type. All other suggestions eliminate the output randomness that is supposedly being tested, making the "test for randomness" pointless.

Related

Is it possible, in JavaScript, to eliminate code branches by tracking their arguments?

I tried to find some tool that would do this, but prepack is not quite doing what I want and other tools are failing at this particular example.
I think it's quite common in programming to use functions in which some of the arguments are constants and the remainder are variables. A good example in JS is parseInt(someNumberToParse, 10).
If I were to write a similar function like this in JS and only ever use it with 10 as a second argument, we could optimise our function to remove logic for other bases, however all tools that I know of fail at this to some degree.
This makes me wonder, would it be possible to write a program that could take any code (module or script) that would track values and types as the code is parsed?
TypeScript is doing it in a way - I can use type guards to narrow down possible types.
I know that for modules, values are most often not known, but a silly example like this:
const add = (a, b = undefined) => {
if (b > 10) {
return a + b
}
return a + a
}
export const mul2 = a => add(a)
In this case we know that b will never be larger than 10 and we can safely remove the condition.
In effect, we could just optimise to
export const mul2 = a => a + a
Sometimes we can't know the value, but we know it has a certain type(s) or the value matches some conditions.
Is it possible to do that in JS? Would it be possible to do it in a real program (possibly megabytes of code)?

Limiting values to a variable in Node.js

I'm not sure if this question makes sense but when I'm using an IDE and for example I type:
x = 5
s = typeof(x)
if (s === ) //Cursor selection after === (before i finished the statement)
the IDE's autocomplete feature gives me a list of the possible values. And if I type value that doesn't exist in that list it's highlighted, and when I execute the program (in other examples, not this one), it throws an error.
I want to achieve a similar functionality with my own variables so that I can only assign specific values to it.
I'd recommend using TypeScript. See this question.
For example, your code will throw a TypeScript error if you try to compare the result of typeof against anything that isn't a proper JavaScript type:
x = 5
s = typeof(x)
if (s === 'foobar') {
}
results in
In a reasonable IDE with TypeScript (such as VSCode), any line of code that doesn't make sense from a type perspective will be highlighted with the error.
If you want to permit only particular values for some variable, you can use | to alternate, eg:
let someString: 'someString' | 'someOtherString' = 'someString';
will mean that only those two strings can occur when doing
someString =
later.
TypeScript makes writing large applications so much easier. It does take some time to get used to, but it's well worth it IMO. It turns many hard-to-debug runtime errors into (usually) trivially-fixable compile-time errors.

Is there a way to protect your code from Javascript quirk `Array(length) vs Array(el1,el2,...)` with Typescript

I'm not looking for other ways to copy an array. My question is particularly about types.
Typescript has nothing against this kind of code (playground):
const sum = original_numbers => {
const numbers_copy = new Array(...original_numbers) // here is the problem
const res = numbers_copy.reduce((acc,v) => acc+v,0)
console.log(res)
return res
}
sum([1,2]) // 3 as expected
sum([1 ]) // 0 !!! And typescript doesn't complain. You can check the playground.
Is there anything that can be done about it?
The Array constructor has problems (including this one). With TSLint, you can use the prefer-array-literal rule to forbid such uses of new Array.
For ESLint, you can use no-array-constructor.
To create an array from arguments, consider using Array.of instead.
The Array constructor is problematic enough that there's no "good" way to give it a type definition that works for all use cases. The standard library's definition for it looks like
interface ArrayConstructor {
new(arrayLength?: number): any[];
new <T>(arrayLength: number): T[];
new <T>(...items: T[]): T[];
}
so you are likely to get an array with elements of type any, which is intentionally unsound, letting you do things that might not be safe without complaint.
If you want a safer version of this you might want to use declaration merging (and see global augmentation if your code is in a module) to use the unknown type instead:
interface ArrayConstructor {
new(arrayLength?: number): unknown[];
}
At this point, your original code will error like this:
const sum_ = (original_numbers: number[]) => {
const numbers_copy = new Array(...original_numbers) // unknown[]
const res = numbers_copy.reduce((acc, v) => acc + v, 0) // error!
// ---------------------------------------> ~~~ ~
// object is of type unknown
console.log(res)
return res
}
because numbers_copy turns out to maybe not be an array of numbers. If you want to fix that, then you need to change how you call new Array() so that the compiler is convinced you're getting a number[]. Possibly like this:
const sum = (original_numbers: number[]) => {
const numbers_copy = new Array(0, 0, ...original_numbers) // number[]
const res = numbers_copy.reduce((acc, v) => acc + v, 0) // okay
console.log(res)
return res
}
sum([1, 2]) // 3 as expected
sum([1]) // 1 as expected
That's kind of silly, but adding two more 0s ensures that you're getting an actual array of numbers, and 0 doesn't affect the sum. Obviously the "right" thing to do is to stay away from new Array(...someOtherArray) and use one of the many well-behaved methods to copy arrays. You know that, though.
The underlying conflict you're having is that you maybe expected TypeScript to save you from this automatically. The problem is that TypeScript is a valiant effort to give a useful static type system to JavaScript, which is dynamically typed and arguably weakly typed. It can do all sorts of crazy things at runtime, some of which people actually rely on. If TypeScript were to be tightened up so much as to prevent these, it would end up being a legalistic and annoying language to use.
So TypeScript is, for better or worse, unsound in places. This is summed up in TypeScript Design Non-Goal #3: it is not a design goal of TypeScript to apply a sound or "provably correct" type system. Instead, the goal is to strike a balance between correctness and productivity.
The particular point at which correctness becomes more or less importance than productivity (or where productivity is actually reduced by having to fix potentially catchable issues at runtime) is subjective and different people have different opinions. For example, you might want to generalize the problem here where any in a library signature hides potential problems, and you'd prefer that unknown be used everywhere instead. There's an open issue for that: microsoft/TypeScript#26188. If so, you might want to give that a 👍 and give a compelling description of why you want it.
I've often joked that there should be a TypeScript Unsoundness Support Group to help people deal with the unfortunate reality of the language's type safety limitations. Especially because those of us who have more or less come to accept them can come off as flippant when others run into them for the first time.
Playground link to code

Real Password Cracker - Codewars Challenge - Javascript

There is a challenge on Codewars that asks you to decipher SHA-1 hashes.
(I think) I need to require Crypto in order to do so. I found this example of how to create SHA-1 Hash from a String in JS using Crypto:
let x = "Geek"
function createSha1 (x) {
const crypto = require('crypto'),
let hashPwd = crypto.createHash('sha1').update(x).digest('hex');
return hashPwd;
}
So then basically I need to do the opposite, correct? The argument is given to the function as a SHA-1 hash, so we need to take that and turn it into a string - How can you decode a SHA-1 hash? Because according to this article, you can't.
It was suggested by a friend that I would need to
generate the hash, and then start looping and generating it for “a”, “b”, “c”, …“aa”, “ab”, “ac”… etc, and stop when the hashes match and return it.
So then to generate 'normal' hash, I would do something like:
function stringToHash(string) {
let hash = 0;
if (string.length == 0) return hash;
for (let i = 0; i < string.length; i++) {
let char = string.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return hash;
}
But of course, I don't know what string I should use for the argument there, because Codewars is giving us SHA-1 hashes as arguments already: e6fb06210fafc02fd7479ddbed2d042cc3a5155e.
It's the nature of this site, but I hate to post an answer to this challenge right away. Please give hints / direction prior to a working solution first if possible.
Thanks!
Brute force or dictionary attack
In general, you can't reverse hashes. What you can do instead is to try various plausible candidates for the input data, hash them, and check if you got the correct answer. This is how most 'password hash cracking' works in practice, with various well established tools (hashcat, john the ripper, etc) and online services, however that's probably not relevant since you're expected to code the solution yourself.
The main thing that determines how fast you'll find the solution is your choice of candidate solutions. Looping through all the letters and trying out all possible combinations as your friend suggested - the brute force solution - is a possibility. It's worth noting that it will succeed only if you're looping through the correct 'alphabet' - if you're trying only the lowercase letters, then you will intentionally ignore options that include a number or an uppercase letter or some other symbol.
Another commonly used option is to assume that the password is weak and run a 'dictionary attack', trying out various options that are more likely to be chosen by humans than a random sequence of letters. It may be a literal dictionary, trying English words; it may be a list of known frequently used passwords (e.g. https://github.com/danielmiessler/SecLists has some lists like that), or it may be a dictionary combined with some 'mutation rules' - e.g. if the list includes 'password' a cracking tool might automatically generate and try also 'password2' and 'Password' and 'passw0rd' among other options.
In your particular case the password is weak enough so that both brute force and a dictionary attack will work. For more difficult hashes that won't be the case.
Ideal cryptographic hashes are designed specifically as one way functions, making it infeasible to simply apply an inverse transform to get the plain text back out. Something else you should be aware of is due to the compression nature of hash functions you will have issues with the pigeon hole principal, meaning that multiple things can hash to the the same value.
There are several ways of solving this problem though that don't require you to create an inverse.
Bruteforce
As your friend mentioned, the easiest thing to do would be just to try to brute force the hash. Assuming that they picked something that is say 6 characters long, it should take less than a second. If you know anything about the nature of the password then your work is easier. For example if you are told the password maybe between 4-6 chars long and it contains at least one number and uppercase you can create a character set to use in your brute force. This assumes that the password is a straight hash or with some known salt.
Rainbow Tables
This is somewhat related to brute forcing, but someone has spent the time and precomputed as many possible hashes as they can. You can find these tables online and simply have to look up your hash. Most common passwords, words, phrases, and alphanumeric combinations have been enumerated and can be looked up within several miliseconds. Again these assumes that the values are run through hash as is without salts ect.
Length Extensions
With sha1, you can simply forge something that hashes to the same exact value using something called length extension. This is probably outside of what you need, but is something worth a look if you are really interested in cryptoanalysis.
I don't use that site so not familiar with the format.
It wants you to brute force it, can get it to pass on Test but not on Attempt, it just always times out
Here is the code, knowing its only going to be either code or test we can reduce charset, but it still times out. maybe you know why.
const crypto = require('crypto');
const alpha = 'abcdefghijklmnopqrstuvwxyz';
function* permutator(length = 4, prev = "") {
if (length <= 0) {
yield prev;
return;
}
for (const char of [...alpha])
yield* permutator(length - 1, prev + char);
}
function passwordCracker(hash) {
const it = permutator();
while (true) {
const v = it.next().value
if (v && crypto.createHash('sha1').update(v).digest('hex') === hash)
return v
}
}
Edit, it gives hints that its expecting to see at least 5 chars, if you fake it, with something like:
function passwordCracker(hash) {
// Good Luck
let map = {
'e6fb06210fafc02fd7479ddbed2d042cc3a5155e': 'code',
'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3': 'test',
}
return map[hash];
}
Errors with:
Test Results:
Fixed tests
testing...
expected undefined to equal 'try'
...
harder testing...
expected undefined to equal 'cgggq'
So that means you can't cheat with a reduced charset, it will need to be a-z, work backwards (because it will pass before 5) and be at least 5 long.
On my computer, the above code takes way longer than 12seconds which is the limit :(

Javascript: What is a nice curry example? [duplicate]

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.

Categories

Resources