5 ms·
I think this is another instance of solving the wrong problem. var a = getData(); if (a != null) { var b = getMoreData(a); if (b != null) {
by jstimpfle 9y ago
I think this is another instance of solving the wrong problem.
var a = getData();
if (a != null) {
var b = getMoreData(a);
if (b != null) {
var c = getMoreData(b);
if (c != null) {
var d = getEvenMoreData(a, c)
if (d != null) {
print(d);
}
}
}
}
Why not simply
var a = getData();
if (a == null)
return;
var b = getMoreData(a);
if (b == null)
return;
var c = getMoreData(b);
if (c == null)
return;
var d = getEvenMoreData(a, c)
if (d == null)
return;
print(d);
And the other example
var a = getData();
for (var a_i in a) {
var b = getMoreData(a_i);
for (var b_j in b) {
var c = getMoreData(b_j);
for (var c_k in c) {
var d = getMoreData(c_k);
for (var d_l in d) {
print(d_l);
}
}
}
}
Yes, there is the issue that there is too much nesting. But there is no point in tackling this problem with a clever monad. That's not solving the issue, it's just hiding it. Operationally there is no difference.
What really needs to be done is to avoid data dependencies. It's typically possible to do something like
for (var x in a)
foo(x, a_state);
for (var x in b)
bar(x, a_state, b_state);
for (var x in c)
baz(x, a_state, b_state, c_state);
for (var x in d)
quux(x, a_state, b_state, c_state, d_state);
This not only looks cleaner, it is cleaner. The path of execution is simpler. It will also often run much faster, since its only tight loops and uniform data accesses.
- j_m_b 9y ago>Why not simply Because people are too busy demonstrating how smart and talented they are. Simple, clean code is too dumb.
- zoul 9y ago> That's not solving the issue, it's just hiding it. Operationally there is no difference. It don’t think that’s a fair argument against abstraction and syntax improvements.
- jstimpfle 9y agoI'm not making an argument against (good) abstraction, or practical syntax. Don't you agree that it is better to solve the problem where it is: at a lower level?
- zoul 9y agoI don’t consider your example of error handling superior to the Maybe monad. It’s more explicit and arguably simpler, but has more boilerplate and is less safe.
- tathougies 9y agoYour last example of keeping multiple states is less legible than using the list monad. Also, some problems are naturally highly dependent, like matrix multiplication
- lobster_johnson 9y agoThe example in the article opens itself to an attack like this because it's simple (in an attempt at explaining things simply). It's easy to mistake the trivialness for naivety. But the "hell" part that monads solve really arise when you go further than this -- when you have error handling, null handling and asynchronicity and mutable state involved. For example, if each of these functions could return an Either or Maybe, your non-monadic, "if"-based version would get a lot hairier. Monads abstract and generalize the concept of chaining computations. Of course you can write the chaining manually, but you would have to replicate the same logic for every chain of function calls, with all the ad-hoc error handling and so on in place. It may look "cleaner" to you, but there's no generalization happening, and monads exist to generalize patterns like these into a single tool that can used over and over again. This is why every single monad code example in the article is identical.
- jstimpfle 9y agoYes, you can implement an "error monad" instance for each of a given set of procedures (returning Either, Maybe, or whatever). You can also wrap each of a given set of procedures that don't conform to a uniform interface (say, return null or < 0 on error) to be conformant. That's just basic hygiene. I don't see a problem. > Monads abstract and generalize the concept of chaining computations. I get that, but in the real world I don't find any need beyond sequencing (first do this, then do that) and the occasional nested-for or early return. Everything else is only giving up on other things that are extremely important, like modularity (complex types / protocols are inherently anti-modular) and deterministic resource usage. > This is why every single monad code example in the article is identical. I didn't even notice that, and I do not consider this a desirable goal at all. The examples do totally different things, and you want to see that. There's no need to swap one out for the other in any realistic scenario. Ever.
- dllthomas 9y ago> in the real world I don't find any need And I'm sure you're pretty productive with your choice of language, but bear in mind that tools shape our thinking. You don't find yourself reaching for those tools in part because you've never expected them to be there. That doesn't mean they can't be very useful.