Reputation: 500
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?
Upvotes: 3
Views: 502
Reputation: 198496
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
.
Upvotes: 2
Reputation: 21451
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
Upvotes: 1