Very nice article! (Up also on Reddit)
> We can easily create small components, which are easily composed because they are stateless and side-effect free, and through that achieve reusable code
Well said, we are on the same page.
Now for what concerns the implementation, since I'm facing the same process (design a framework revolving around React for didactic purposes) I'd like to know your opinion on these points / issues:
- components are defined with an alternative syntax that uses positional arguments and breaks jsx. Is it necessary? I can see it's very nice for simple, small components though.
- local state is discouraged but still accessible, you gain in adoption and pragmatism but lose the stateless and side-effect free thing
- "statics" means something like controllers? It's not clear to me
- cursors are cool, but the `props.cursor.get('name')` syntax worries me, mainly the use of strings. Besides, in your excellent model where the state is immutable, why I can't directly access the component data and I'm forced to use the cursor? I guess for the updating stuff, but in general it seems unlikely that a view had the knowledge to update directly the app state without a mediator (a controller passed as statics?)
The good news is that `Object.freeze` is your best friend mainly in the design/development phase.
So it can be placidly "shimmed" with the identity function.
Great article and nice ilustrations :) Bravo!
It worth mentioning again the Fantasy land project, aka "Algebraic JavaScript Specification":
https://github.com/fantasyland
(Algebra was my favorite subject at university)
When I see concepts like transducers I'm always torn in two:
**my theoretical side** is excited: reducing (pun intended) a bunch of different operations to a minimal set of basic, composable operations is an awesome intellectual challenge.
I imagine how succinct, reusable and multipurpose could become my code.
**my pragmatic side** is skeptic: in functional programming it's a little step to end up with incomprehensible code, for me and my coworkers:
var inc = function(n) { return n + 1; };
var isEven = function(n) { return n % 2 == 0; };
var xf = comp(map(inc), filter(isEven));
console.log(into([], xf, [0,1,2,3,4])); // [2,4]
vs
var inc = function(n) { return n + 1; };
var isEven = function(n) { return n % 2 == 0; };
[0,1,2,3,4].map(inc).filter(isEven); // [2,4]
The latter is comprehensible by everyone (and no additional library).
Ok you iterate twice but if you really (REALLY) have performance problems, maybe you'd end up
with something like this:
var input = [0,1,2,3,4];
var output = [];
var x;
for (var i = 0, len = input.length ; i < len ; i++ ) {
x = input[i] + 1; // map
if (x % 2 == 0) ouput.push(x); // filter
}
> Single argument doesn't capture required/optional semantics.
I disagree. As shown here (section "Tuples and Structs")
http://gcanti.github.io/2014/09/29/javascript-types-and-sets.html
tuples and hashes are theoretically equivalent, but
I'd prefer to stick the required/optional semantic to the property:
var Person = struct({
name: Str, // required string
surname: maybe(Str), // optional string
email: maybe(Str) // optional string
});
rather than rely on an arbitrary order: `Person(name, [surname], [email])`, but it could be also `Person(name, [email], [surname])` or `Person([email], name, [surname])` ...
> I think a hybrid approach is best.
Without arguments, I'm forced to interpret it as an expression of taste, so I automatically and kindly agree with you.
> Also isn't discoverable, requires reading docs or source.
I disagree. The meta info of the `Person` type (name, surname, email)
are easily parseable (you don't even need esprima for that)
since they are expressed in vanilla JavaScript rather than opaque comments like JsDocs.
This is an example of what I'm saying:
http://gcanti.github.io/resources/tcomb-react-bootstrap/playground/playground.html
When you make a mistake I automatically display the docs.
The docs are generated on the fly analyzing a domain model written with the same style of the `Person` above.
IDE support is straightforward to obtain.
> Another option is fluent APIs.
I generally don't like fluent APIs:
- they are cumbersome for the developer designing the API
- they produce dangerous, temporary, intermediate, invalid type values during the construction
- required/optional semantic is a mess to implement since quite all properties must be temporary optional
- it's not clear when the building process can be considered terminated
Pasted from Reddit:
While typically in functional programming articles the emphasis is on functions, in what I call "Math Driven Design" or "Mathematical Programming" the emphasis is on sets, as fundamental building block. The ultimate goal of these articles (two I think) is to show, **in a pragmatic way**, a parallel like this:
domain models -> series of set definitions
functions -> theorems
Hello,
this is an attempt to write a divulgative article on Math (for which I have a genuine passion) with some practical implications in JavaScript and trying to show a different point of view.
I hope you enjoy it!