3 ms·
I did not say "can't do". I essentially said "not as well". Of course "well" can be subjective, but if enough people don't like way a given language/tool does
by tabtab 8y ago
I did not say "can't do". I essentially said "not as well". Of course "well" can be subjective, but if enough people don't like way a given language/tool does it, they will ignore it, like they have been with FP/logical programming for several decades. Somebody needs to articulate in careful unambiguous detail how and why it's "better" and "easier", not just repeatedly claim it. That writer apparently hasn't been born yet.
- the_af 8y agoAt least some of your assumptions are wrong: no-one is ignoring FP anymore.
- tabtab 8y agoThey don't have a choice: the latest languages force it on you by not giving better alternatives. For example, their stiff object models. For instance, why the heck can't one easily attach an on-click method to a Java button, instead forced to use silly lambdas? It would be more natural and simpler. Over-focus on FP damaged the OOP improvements/designs. Each generation seems to over-do something, and then the pendulum swings the other way.
- the_af 8y agoI don't understand your example (and I don't understand why you consider lambdas silly), but more importantly: if most of the world -- by which I mean, modern language designers and practitioners -- seems to be going one direction, and you insist in staying put, aren't you at least a bit worried you might be wrong about it? "It" being the partial adoption of FP idioms and features in this case.
- chriswarbo 8y agoYou seem to be moving the goalposts to "why is FP better than X". I was simply pointing out that printf debugging is easy in FP. In fact, it's probably easier in FP, since everything is an expression, whereas imperative languages have a weird expression/statement distinction. For example, if I have code like: buggyCode x y = if foo x then bar x y else baz y I can wrap anything on the right-hand-side in a printf (except the keywords if/then/else). At the extreme end I could do: buggyCode x y = trace "hit buggy code" (if trace "applying foo to x" ((trace "hit foo" foo) (trace "hit foo's x" x) then trace "applying bar x to y" ((trace "applying bar to x" ((trace "hit bar" bar) (trace "hit bar's x" x))) (trace "hit bar's y" y)) else trace "applying baz to y" ((trace "hit baz" baz) (trace "hit baz's y" y)) I could even move the x and y arguments across to the right-hand-side using anonymous function notation, then I can trace partial applications too: buggyCode = trace "hit buggyCode" (\x -> trace "gave x to buggyCode" (\y -> trace "gave y to buggyCode" <previous right-hand-side goes here>)) Note that we the built-in if/then/else is mostly a legacy crutch to aid familiarity. We can just use a function instead, and printf all the things: ifThenElse True x y = x ifThenElse False x y = y buggyCode = \x -> (\y -> (ifThenElse (foo x) (bar x y) (baz y))) (Of course, defining our own if/then/else isn't much use; we're usually better off writing more meaningful, domain-specific alternatives)
- tabtab 8y agoThat's another thing: "high-meta" languages allow individual developers to re-invent the flow-control wheel in their own image (personal preferences). Consistency is often more important for team readability than factoring (compact code). One man's "clever" can be another's spaghetti code. What works well for individual projects often doesn't scale to larger and often-changing teams.
- chriswarbo 8y agoThat argument can certainly be applied to Lisps, with their extensive macro systems, but that's mostly orthogonal to programming paradigm. Lisps aren't necessarily functional: Common Lisp is highly imperative, and even Scheme is 'the ultimate imperative' https://dspace.mit.edu/handle/1721.1/5790 https://dspace.mit.edu/handle/1721.1/5790 ! As for that `ifThenElse` example, there's nothing "meta" going on at all and there's no fancy control flow: it's just a (very simple) function. Consider a function like: renderPage User page register = page renderPage Guest page register = register Doesn't look like 'clever spaghetti' to me: we branch between 'User' and 'Guest', returning a different one of our arguments for each. Yet this is identical to that 'ifThenElse' function, except for the names (which are irrelevant to the machine). This is what I meant by writing "more meaningful, domain-specific alternatives". Not to "re-invent control flow", but to avoid talking about control flow, and just use functions. Note that we can do pretty much the same in any language, e.g. Python: def ifThenElse(c, x, y): return {True: x, False: y}[c] def renderPage(session, page, register): return {User: page, Guest: register}[session] Nothing "meta" or "re-inventing the flow-control wheel" there; just some functions. Of course, this isn't a great idea in Python since Python is impure and uses eager evaluation. Note that such "meta" "reinvented control structures" appear all over the place in OOP, due to dynamic dispatch, e.g. class User: def renderPage(page, register): return page class Guest: def renderPage(page, register): return register These are the two solutions to the "expression problem": - FP restricts the allowed values but allows new functions to use them. For example, adding an Admin session would be hard (need to rewrite renderPage), but adding a renderAvatar function is easy. - OOP restricts the allowed functions (methods), but allows them to use new values. For example, adding an Admin class would be easy, but adding a renderAvatar method would be hard (need to rewrite User and Guest).