Understanding Ramda.js - javascript

Question 1:
var _curry1 = function _curry1(fn) {
return function f1(a) {
if (arguments.length === 0) {
return f1;
} else if (a != null && a['##functional/placeholder'] === true) {
return f1;
} else {
return fn.apply(this, arguments);
}
};
};
What is the purpose of checking a['##functional/placeholder'] === true ?
Question 2:
http://ramdajs.com/0.18.0/docs/#reduce
How do I read the notation?
(a,b -> a) -> a -> [b] -> a
This is my first time seeing such notation, where does it come from?

Question 1:
There is no "notation". __.js should clear it up:
module.exports = {'##functional/placeholder': true};
so ##functional/placeholder is no different than foo in
a = { foo: true }
a.foo
a["foo"]
(Obviously, you can't write a.##functional/placeholder because of all the odd symbols there.)
The intent is also seen in that file:
/**
* A special placeholder value used to specify "gaps" within curried functions,
* allowing partial application of any combination of arguments,
* regardless of their positions.
*
* If `g` is a curried ternary function and `_` is `R.__`, the following are equivalent:
*
* - `g(1, 2, 3)`
* - `g(_, 2, 3)(1)`
* - `g(_, _, 3)(1)(2)`
* - `g(_, _, 3)(1, 2)`
* - `g(_, 2, _)(1, 3)`
* - `g(_, 2)(1)(3)`
* - `g(_, 2)(1, 3)`
* - `g(_, 2)(_, 3)(1)`
...
So the intent is to be able to "skip" some places when currying. The test decides whether an argument is a real argument or the __.js placeholder, and behaves accordingly. Why it is ##functional/placeholder - presumably precisely because it is hoped that it is too weird, and will thus not collide with anyone's legitimate data.
Question 2:
The notation is standard in type theory, and popularised by Haskell. a and b are any types. (...) is a tuple of types, [a] is an list whose elements are a. a -> b is a function that takes an argument of type a and yields a return of type b, and is right-associative. The example in question reads:
It is a function that takes an argument a function that takes two arguments (of types a and b respectively) and returns a value of type a; and yields a function that takes an argument of type a and returns a function that takes an argument that is a list of elements of type b, returning a value of type a.
This reads very confusingly, but an uncurried description will be a bit easier: it is a function that takes three arguments: the first one being a function (as described above), the second one being a value of a, the third one being a list of b elements, and returns a value of a.
Specifically, R.reduce is such a function: in
R.reduce(add, 10, numbers);
add is a function that takes two integers (both a and b being the same, integer), and returns an integer ((a, b) -> a); 10 is of type integer (a); numbers is a list of integers ([b]); and the return value is an integer (a).
Note that it mixes curried and uncurried syntax; if it was fully curried, add would be a -> b -> a, not (a, b) -> a.

Question 2:
That is a Hindley-Milner type signature. For the example given, 'a' and 'b' are arbitrary types and '->' is a function.
So lets break it down.
First, we take a type 'a' and a function 'b -> a'
(a, b -> a)
This returns a function, which returns a function,.. (cause you know, currying). The point is we can add '()' to make it a bit more readable.
(a, b -> a) -> (a -> ([b] -> a))
So if you pass this function 'a' and a function 'a' -> 'b', you get back
a -> ([b] -> a)
And if you pass this a type 'a'
[b] -> a
Where [b] is an array of type 'b's. Passing this function [b] gives you
a type a
a
If you want to read more about functional programming in JavaScript, I can recommend The Mostly Adequate Guide

Related

jQuery .sort() function working in Safari and Firefox but not in Chrome [duplicate]

I have always successfully sorted my arrays like this (when I did not want the standard lexicographic ordering):
var arr = […] // some numbers or so
arr.sort(function(a, b) {
return a > b;
});
Now, someone told me this was wrong, and that I would need to return a-b instead. Is that true, and if yes why? I have tested my comparison function, and it works! Also, why would my solution be so common when it is wrong?
TL;DR
I have always successfully sorted my arrays like this
No, you have not. And didn't notice it. Some quick counterexamples:
> [0,1,0].sort(function(a,b){ return a>b })
Array [0, 1, 0] // in Chrome, in Internet Exploder 11.
// Results may vary between sorting algorithm implementations
> [1,1,0,2].sort(function(a, b){ return a>b })
Array [0, 1, 2, 1] // in Opera 12.
Array [1, 1, 0, 2] // in Chrome 100, in Internet Exploder 11.
// Results will vary between sorting algorithm implementations
why?
Because your comparison function does return false (or 0, equivalently) even when b is larger than a. But 0 implies that the two elements are considered equal - and the sorting algorithm believes that.
In-Depth Explanation
Comparison functions in JavaScript
How do comparison functions work?
The Array::sort method can take an optional, custom comparison function as its argument. That function takes two arguments (commonly referred to as a and b) which it should compare, and is supposed to return a number
> 0 when a is considered larger than b and should be sorted after it
== 0 when a is considered equal to b and it doesn't matter which comes first
< 0 when a is considered smaller than b and should be sorted before it
If it does not return a number, the result will be cast to a number (which is handy for booleans). The returned number does not need to be exactly -1 or 0 or 1 (though it typically is).
Consistent ordering
To be consistent, the compare function would need to fulfill the equation
comp(a, b) == -1 * comp(b, a)
// or, if values other than -1, 0 and 1 are considered:
comp(a, b) * comp(b, a) <= 0
If that requirement is broken, the sort will behave undefined.
Citing the ES5.1 spec on sort (same thing in the ES6 spec):
If comparefn is […] not a consistent comparison function for the elements of this array, the behaviour of sort is implementation-defined.
A function comparefn is a consistent comparison function for a set of values S if all of the requirements below are met for all values a, b, and c (possibly the same value) in the set S: The notation a <CF b means comparefn(a,b) < 0; a =CF b means comparefn(a,b) = 0 (of either sign); and a >CF b means comparefn(a,b) > 0.
Calling comparefn(a,b) always returns the same value v when given a specific pair of values a and b as its two arguments. Furthermore, Type(v) is Number, and v is not NaN. Note that this implies that exactly one of a <CF b, a =CF b, and a >CF b will be true for a given pair of a and b.
Calling comparefn(a,b) does not modify the this object.
a =CF a (reflexivity)
If a =CF b, then b =CF a (symmetry)
If a =CF b and b =CF c, then a =CF c (transitivity of =CF)
If a <CF b and b <CF c, then a <CF c (transitivity of <CF)
If a >CF b and b >CF c, then a >CF c (transitivity of >CF)
NOTE: The above conditions are necessary and sufficient to ensure that comparefn divides the set S into equivalence classes and that these equivalence classes are totally ordered.
Uh, what does this mean? Why should I care?
A sorting algorithm needs to compare items of the array with each other. To do a good and efficient job, it must not need to compare each item to every other, but needs to be able to reason about their ordering. For that to work well, there are a few rules that a custom comparison function needs to abide. A trivial one is that an item a is equal to itself (compare(a, a) == 0) - that's the first item in the list above (reflexivity). Yes, this is a bit mathematical, but pays of well.
The most important one is transitivity. It says that when the algorithm has compared two values a and b, and also b with c, and has found out by applying the comparison function that e.g. a = b and b < c, then it can expect that a < c holds as well. This seems only logical, and is required for a well-defined, consistent ordering.
But your comparison function does fail this. Lets look at this example:
function compare(a, b) { return Number(a > b); }
compare(0, 2) == 0 // ah, 2 and 0 are equal
compare(1, 0) == 1 // ah, 1 is larger than 0
// let's conclude: 1 is also larger than 2
Ooops. And that is why a sorting algorithm can fail (in the spec, this is be "implementation-dependent behaviour" - i.e. unpredictable results) when it is invoked with a comparison function that is not consistent.
Why is the wrong solution so common?
Because in many other languages, there are sorting algorithms that don't expect a three-way comparison but merely a boolean smaller-than operator. C++ std::sort is a good example of that. It will simply be applied twice with swapped arguments if an equality needs to be determined. Admittedly, this can be more efficient and is less error-prone, but needs more calls to the comparison function if the operator cannot be inlined.
CounterExamples
I have tested my comparison function, and it works!
Only by sheer luck, if you tried some random example. Or because your test suite is flawed - incorrect and/or incomplete.
Here is the small script I used to find the above minimal counterexample:
function perms(n, i, arr, cb) {
// calls callback with all possible arrays of length n
if (i >= n) return cb(arr);
for (var j=0; j<n; j++) {
arr[i] = j;
perms(n, i+1, arr, cb);
}
}
for (var i=2; ; i++) // infinite loop
perms(i, 0, [], function(a) {
if ( a.slice().sort(function(a,b){ return a>b }).toString()
!= a.slice().sort(function(a,b){ return a-b }).toString() )
// you can also console.log() all of them, but remove the loop!
throw a.toString();
});
What comparison function is correct?
Use no comparison function at all, when you want a lexicographic sort. Items in the array will be stringified if necessary.
A generic comparison function that works like the relational operators can be implemented as
function(a, b) {
if (a > b) return 1;
if (a < b) return -1;
/* else */ return 0;
}
With a few tricks, this can be minified to the equivalent function(a,b){return +(a>b)||-(a<b)}.
For numbers, you can simply return their difference, which abides all the laws above:
function(a, b) {
return a - b; // but make sure only numbers are passed (to avoid NaN)
}
If you want to sort in reverse, just take the appropriate one and swap a with b.
If you want to sort composite types (objects etc), replace each a and each b with an access of the properties in question, or a method call or whatever you want to sort by.
The sort function expects a function that expects two arguments a and b, and returns:
A negative number if a comes before b
A positive number if a comes after b
Zero if relative order of a and b does not matter
In order to sort numbers in ascending order return a - b will produce the correct return values; for example:
a b ret
1 2 -1
3 2 1
2 2 0
On the other hand return a > b produces the following return values:
a b ret implied
1 2 false 0
3 2 true 1
2 2 false 0
In the above example, the sort function is told that 1 and 2 are same (and placing 1 before 2 or 2 before 1 does not matter). This will produce incorrect result, for example (in Chrome 49):
console.log([5, 8, 7, 1, 2, 3, 4, 6, 9, 10, 11, 12, 13].sort(function(a, b) {
return a > b;
}));
// [4, 5, 3, 1, 2, 6, 7, 8, 9, 10, 11, 12, 13]

What is the binary operator of Function Monoids in example of JavaScript

In this article Function Monoids are introduced with C# code and Haskell Type definition.
A function a -> b is a monoid if b is a monoid. This means that
you can combine two functions with the same type. In an
object-oriented context, it means that you can combine two methods
with the same signature into one method as long as the return type
forms a monoid.
Generalisation
While the above C# code is only an example, the general rule is that
any function that returns a monoid is itself a monoid. In Haskell,
this rule is articulated in the standard library:
instance Monoid b => Monoid (a -> b)
This means that for any monoid b, a function a -> b is also
(automatically) a monoid.
The problem is the example in C# is too specific about "GUID" and I have no idea what the author trying to do in the code, and the Haskell Type Definition is merely the type definition.
What is an example code in JavaScript to implement this Function Monoids?
cf)
Why is instance Monoid b => Monoid (a -> b) in base?
Monoid Laws
identity law:
combine (identity, a) == combine (a, identity)
associativity law:
combine (a, combine (b, c)) == combine (combine (a, b), c)
We can implement an identity element (identity) and binary operation (combine) for functions -
// identity element
const identity =
x => x
// binary operation
const combine = (a, b) =>
x => a (b (x))
// sample functions
const a =
x => x + 3
const b =
x => x - 1
const c =
x => x * x
// uphold laws
console.log
( combine (identity, a) (2) === combine (a, identity) (2)
, combine (a, combine (b, c)) (2) === combine (combine (a, b), c) (2)
)
// => true
// => true
The binary operation and identity element is different depending on your domain. See the table on Wikipedia for more insight on how to implement the identity element and binary operation for various sets.
Of course you are not limited to those domains. Your custom type may have various binary operations and identity elements that satisfy the monoid laws. If the laws are upheld, your type belongs to the monoid category.
It's important to know that being able to combine things doesn't necessarily mean they are a monoid. For something to be a Monoid, it must have associativity, left identity, and right identity.
C#:
public static Func<Guid, int> Combine(
Func<Guid, int> f,
Func<Guid, int> g)
{
return x => f(x) + g(x);
}
JS:
function combine(f,g) {
return x => f(x) + g(x)
}
function addOne(x) {
return x + 1;
}
function addTwo(x) {
return x + 2;
}
let newFunction = combine(addOne, addTwo);
let result = newFunction(0);
console.log(result)

type checking helper with Ramda

I want to write a function whose specifications is described in the piece of code below which is the current implementation I have. It does work. However I have been trying for a while to write it pointfree and entirely as a composition of ramda functions and could not find a solution. The issue is linked to obj => map(key => recordSpec[key](obj[key]) which I cannot reduce in a way that I can write the whole thing pointfree.
How could I do?
/**
* check that an object :
* - does not have any extra properties than the expected ones (strictness)
* - that its properties follow the defined specs
* Note that if a property is optional, the spec must include that case
* #param {Object.<String, Predicate>} recordSpec
* #returns {Predicate}
* #throws when recordSpec is not an object
*/
function isStrictRecordOf(recordSpec) {
return allPass([
// 1. no extra properties, i.e. all properties in obj are in recordSpec
// return true if recordSpec.keys - obj.keys is empty
pipe(keys, flip(difference)(keys(recordSpec)), isEmpty),
// 2. the properties in recordSpec all pass their corresponding predicate
// For each key, execute the corresponding predicate in recordSpec on the
// corresponding value in obj
pipe(obj => map(key => recordSpec[key](obj[key]), keys(recordSpec)), all(identity)),
]
)
}
For instance,
isStrictRecordOf({a : isNumber, b : isString})({a:1, b:'2'}) -> true
isStrictRecordOf({a : isNumber, b : isString})({a:1, b:'2', c:3}) -> false
isStrictRecordOf({a : isNumber, b : isString})({a:1, b:2}) -> false
One way to achieve this would be to use R.where, which takes a spec object like your recordSpec and applies each predicate with the value from the corresponding keys of the second object.
Your function would then look like:
const isStrictRecordOf = recordSpec => allPass([
pipe(keys, flip(difference)(keys(recordSpec)), isEmpty),
where(recordSpec)
])

Sorting in JavaScript: Shouldn't returning a boolean be enough for a comparison function?

I have always successfully sorted my arrays like this (when I did not want the standard lexicographic ordering):
var arr = […] // some numbers or so
arr.sort(function(a, b) {
return a > b;
});
Now, someone told me this was wrong, and that I would need to return a-b instead. Is that true, and if yes why? I have tested my comparison function, and it works! Also, why would my solution be so common when it is wrong?
TL;DR
I have always successfully sorted my arrays like this
No, you have not. And didn't notice it. Some quick counterexamples:
> [0,1,0].sort(function(a,b){ return a>b })
Array [0, 1, 0] // in Chrome, in Internet Exploder 11.
// Results may vary between sorting algorithm implementations
> [1,1,0,2].sort(function(a, b){ return a>b })
Array [0, 1, 2, 1] // in Opera 12.
Array [1, 1, 0, 2] // in Chrome 100, in Internet Exploder 11.
// Results will vary between sorting algorithm implementations
why?
Because your comparison function does return false (or 0, equivalently) even when b is larger than a. But 0 implies that the two elements are considered equal - and the sorting algorithm believes that.
In-Depth Explanation
Comparison functions in JavaScript
How do comparison functions work?
The Array::sort method can take an optional, custom comparison function as its argument. That function takes two arguments (commonly referred to as a and b) which it should compare, and is supposed to return a number
> 0 when a is considered larger than b and should be sorted after it
== 0 when a is considered equal to b and it doesn't matter which comes first
< 0 when a is considered smaller than b and should be sorted before it
If it does not return a number, the result will be cast to a number (which is handy for booleans). The returned number does not need to be exactly -1 or 0 or 1 (though it typically is).
Consistent ordering
To be consistent, the compare function would need to fulfill the equation
comp(a, b) == -1 * comp(b, a)
// or, if values other than -1, 0 and 1 are considered:
comp(a, b) * comp(b, a) <= 0
If that requirement is broken, the sort will behave undefined.
Citing the ES5.1 spec on sort (same thing in the ES6 spec):
If comparefn is […] not a consistent comparison function for the elements of this array, the behaviour of sort is implementation-defined.
A function comparefn is a consistent comparison function for a set of values S if all of the requirements below are met for all values a, b, and c (possibly the same value) in the set S: The notation a <CF b means comparefn(a,b) < 0; a =CF b means comparefn(a,b) = 0 (of either sign); and a >CF b means comparefn(a,b) > 0.
Calling comparefn(a,b) always returns the same value v when given a specific pair of values a and b as its two arguments. Furthermore, Type(v) is Number, and v is not NaN. Note that this implies that exactly one of a <CF b, a =CF b, and a >CF b will be true for a given pair of a and b.
Calling comparefn(a,b) does not modify the this object.
a =CF a (reflexivity)
If a =CF b, then b =CF a (symmetry)
If a =CF b and b =CF c, then a =CF c (transitivity of =CF)
If a <CF b and b <CF c, then a <CF c (transitivity of <CF)
If a >CF b and b >CF c, then a >CF c (transitivity of >CF)
NOTE: The above conditions are necessary and sufficient to ensure that comparefn divides the set S into equivalence classes and that these equivalence classes are totally ordered.
Uh, what does this mean? Why should I care?
A sorting algorithm needs to compare items of the array with each other. To do a good and efficient job, it must not need to compare each item to every other, but needs to be able to reason about their ordering. For that to work well, there are a few rules that a custom comparison function needs to abide. A trivial one is that an item a is equal to itself (compare(a, a) == 0) - that's the first item in the list above (reflexivity). Yes, this is a bit mathematical, but pays of well.
The most important one is transitivity. It says that when the algorithm has compared two values a and b, and also b with c, and has found out by applying the comparison function that e.g. a = b and b < c, then it can expect that a < c holds as well. This seems only logical, and is required for a well-defined, consistent ordering.
But your comparison function does fail this. Lets look at this example:
function compare(a, b) { return Number(a > b); }
compare(0, 2) == 0 // ah, 2 and 0 are equal
compare(1, 0) == 1 // ah, 1 is larger than 0
// let's conclude: 1 is also larger than 2
Ooops. And that is why a sorting algorithm can fail (in the spec, this is be "implementation-dependent behaviour" - i.e. unpredictable results) when it is invoked with a comparison function that is not consistent.
Why is the wrong solution so common?
Because in many other languages, there are sorting algorithms that don't expect a three-way comparison but merely a boolean smaller-than operator. C++ std::sort is a good example of that. It will simply be applied twice with swapped arguments if an equality needs to be determined. Admittedly, this can be more efficient and is less error-prone, but needs more calls to the comparison function if the operator cannot be inlined.
CounterExamples
I have tested my comparison function, and it works!
Only by sheer luck, if you tried some random example. Or because your test suite is flawed - incorrect and/or incomplete.
Here is the small script I used to find the above minimal counterexample:
function perms(n, i, arr, cb) {
// calls callback with all possible arrays of length n
if (i >= n) return cb(arr);
for (var j=0; j<n; j++) {
arr[i] = j;
perms(n, i+1, arr, cb);
}
}
for (var i=2; ; i++) // infinite loop
perms(i, 0, [], function(a) {
if ( a.slice().sort(function(a,b){ return a>b }).toString()
!= a.slice().sort(function(a,b){ return a-b }).toString() )
// you can also console.log() all of them, but remove the loop!
throw a.toString();
});
What comparison function is correct?
Use no comparison function at all, when you want a lexicographic sort. Items in the array will be stringified if necessary.
A generic comparison function that works like the relational operators can be implemented as
function(a, b) {
if (a > b) return 1;
if (a < b) return -1;
/* else */ return 0;
}
With a few tricks, this can be minified to the equivalent function(a,b){return +(a>b)||-(a<b)}.
For numbers, you can simply return their difference, which abides all the laws above:
function(a, b) {
return a - b; // but make sure only numbers are passed (to avoid NaN)
}
If you want to sort in reverse, just take the appropriate one and swap a with b.
If you want to sort composite types (objects etc), replace each a and each b with an access of the properties in question, or a method call or whatever you want to sort by.
The sort function expects a function that expects two arguments a and b, and returns:
A negative number if a comes before b
A positive number if a comes after b
Zero if relative order of a and b does not matter
In order to sort numbers in ascending order return a - b will produce the correct return values; for example:
a b ret
1 2 -1
3 2 1
2 2 0
On the other hand return a > b produces the following return values:
a b ret implied
1 2 false 0
3 2 true 1
2 2 false 0
In the above example, the sort function is told that 1 and 2 are same (and placing 1 before 2 or 2 before 1 does not matter). This will produce incorrect result, for example (in Chrome 49):
console.log([5, 8, 7, 1, 2, 3, 4, 6, 9, 10, 11, 12, 13].sort(function(a, b) {
return a > b;
}));
// [4, 5, 3, 1, 2, 6, 7, 8, 9, 10, 11, 12, 13]

How can I declare optional function parameters in JavaScript? [duplicate]

This question already has answers here:
Is there a better way to do optional function parameters in JavaScript? [duplicate]
(28 answers)
Closed 3 years ago.
Can I declare default parameter like
function myFunc( a, b=0)
{
// b is my optional parameter
}
in JavaScript?
With ES6: This is now part of the language:
function myFunc(a, b = 0) {
// function body
}
Please keep in mind that ES6 checks the values against undefined and not against truthy-ness (so only real undefined values get the default value - falsy values like null will not default).
With ES5:
function myFunc(a,b) {
b = b || 0;
// b will be set either to b or to 0.
}
This works as long as all values you explicitly pass in are truthy.
Values that are not truthy as per MiniGod's comment: null, undefined, 0, false, ''
It's pretty common to see JavaScript libraries to do a bunch of checks on optional inputs before the function actually starts.
Update
With ES6, this is possible in exactly the manner you have described; a detailed description can be found in the documentation.
Old answer
Default parameters in JavaScript can be implemented in mainly two ways:
function myfunc(a, b)
{
// use this if you specifically want to know if b was passed
if (b === undefined) {
// b was not passed
}
// use this if you know that a truthy value comparison will be enough
if (b) {
// b was passed and has truthy value
} else {
// b was not passed or has falsy value
}
// use this to set b to a default value (using truthy comparison)
b = b || "default value";
}
The expression b || "default value" evaluates the value AND existence of b and returns the value of "default value" if b either doesn't exist or is falsy.
Alternative declaration:
function myfunc(a)
{
var b;
// use this to determine whether b was passed or not
if (arguments.length == 1) {
// b was not passed
} else {
b = arguments[1]; // take second argument
}
}
The special "array" arguments is available inside the function; it contains all the arguments, starting from index 0 to N - 1 (where N is the number of arguments passed).
This is typically used to support an unknown number of optional parameters (of the same type); however, stating the expected arguments is preferred!
Further considerations
Although undefined is not writable since ES5, some browsers are known to not enforce this. There are two alternatives you could use if you're worried about this:
b === void 0;
typeof b === 'undefined'; // also works for undeclared variables

Categories

Resources