Live data from Hacker News

Destroy All Ifs – A Perspective from Functional Programming

degoes.net

131–140 of 226 posts

Re: Destroy All Ifs – A Perspective from Functional Programming

#131
post #6

The idea that each type has its own control flow primitives is bothersome. It's taken over Rust: argv.nth(1) .ok_or("Please give at least one argument".to_owned()) .and_then(|arg| arg.parse:: ().map_err(|err| err.to_string())) .map(|n| 2 * n) I'm waiting for date.if_weekday(|arg| ...) Reading this kind of thing is hard. All those subexpressions are nameless, and usually comment-less. This isn't pure functional progra…

In Haskell, realizing that data flow and control flow are of the same spirit and that data structures are control structures is one of the key epiphanies to be had.

This article mentions 'if' and 'Boolean'. Loops and lists are another example. (And for the same reason that most languages make such extensive use of loops, Haskell programs can often have a lot of lists.)

Re: Destroy All Ifs – A Perspective from Functional Programming

#132

Earlier quoted context omitted.

The annoying part there is the repeated "|x| x.". Rust should have syntax to reference a method of an object, instead of having to write a wrapper. So it'd look like .map_err(???.to_string()).

Groovy and Kotlin use the implicit "it" parameter for lambdas that take just one parameter, which is very convenient: listOf(1, 2, 3, 4).filter { it % 2 == 0 }

And Haskell uses operator sections: (==0) would be similar to { it == 0 }. Alas, the section syntax get a bit cumbersome when you want to compose two or more of them, like in this translation of your example:

    filter ((0==) . (%2)) [1, 2, 3, 4]

Re: Destroy All Ifs – A Perspective from Functional Programming

#133
post #37

Earlier quoted context omitted.

> Try it before you knock it. That's what I recommend too[0] - with the added caveat that you shouldn't be afraid to "knock it" if it turns out to be honestly bad. Sometimes the idea turns out bad, sometimes it turns out great - but you'll never know it if you don't try; just be honest with yourself during that trial. [0] - https://news.ycombinator.com/item?id=12108138

Absolutely, but I'd also add that what works in one language/environment may not work in another. I wouldn't be surprised if writing Haskell-style code in Python didn't work out that well, for example!

I have tried. Two things get in the way quickly, and that's even just expressing thing, not even looking at performance yet:

  * Python standard library functions, especially the ones on dicts, mutate and don't return the new dictionary.
  * Python's syntax for creating functions is awkward: lambdas are cumbersome, and so are the operator package and eg functools.partial; there's no really convenient way to compose functions.

Re: Destroy All Ifs – A Perspective from Functional Programming

#134

I recommend Bob Harper's essay on "boolean blindness": https://existentialtype.wordpress.com/2011/03/15/boolean-bli... An excerpt: > The problem is computing the bit in the first place. Having done so, you have blinded yourself by reducing the information you have at hand to a bit, and then trying to recover that information later by remembering the provenance of that bit.

Thats why you use Lua, it lets you have multiple return values. So you can get a boolean back to let you know if the strings were the same, an int to know where they ceased matching and a boolean to let you know if they are case different. It's then up to the programmer to decide how much enlightenment they want. The destroy all IF reminds me of GOTO considered harmful of the 70's. There are other ways to fix the pro…

What's the difference between multiple return values and returning a tuple?

(Apart from that languages with multiple return values tend to have some special syntax for binding only the first few members of the returned tuple?)

Re: Destroy All Ifs – A Perspective from Functional Programming

#135
post #46

Earlier quoted context omitted.

The Lua solution is clutter. Why return a boolean just to switch on it and then discard it?

Why create a lambda just to execute it and then discard it?

The problem with the Boolean is rather that people mix up the two values all the time.

The lambda also has more type safety. A Boolean is always a Boolean, but the compiler (and in a dynamic language the runtime) can tell you when you are calling your passed functions with the wrong arguments, because you mixed them up.

Re: Destroy All Ifs – A Perspective from Functional Programming

#136
post #116

Earlier quoted context omitted.

The return value of the function is a description of an effect. Calling the function doesn't cause the effect to happen. That's why you could, for example, call the function many times and get a list of IO actions which you then execute in parallel or backwards or whatever. Hence "inversion of control".

I was debating whether on not to put that last sentence because I knew that it would lead to a technical discussion that was aside from the meaning of the question. My question is more -- why choose an `IO ()` as an example of something being called for its value (especially since the article isn't aimed at a Haskell audience)

Yeah, that's probably not a wise decision on part of the author. The IO monad is nifty but of minor importance in the grand scheme of things, and distracts when making a mostly language independent point.

Re: Destroy All Ifs – A Perspective from Functional Programming

#137
post #82

I'm surprised that the article and none of the comments so far mentioned the "Expression Problem": http://c2.com/cgi/wiki?ExpressionProblem Basically, if you structure the control flow in object oriented style (or church encoding...) then its easy to extend your program with new "classes" but if you want to add a new methods then you must go back and rewrite all your classes. On the other hand, if you use if-statemen…

Another alternative is "table-oriented programming", where you define the "classes" and "methods" as an m-by-n structure of code pointers; to add either "methods" or "classes", you would just add a new row/column to the table along with the appropriate code definitions. and because "expression problem" is not a very catchy name. It's also not particularly descriptive either, but the page mentions that it's a form of…

Is that you, TopMind? I used to be on Wiki years ago too...

Re: Destroy All Ifs – A Perspective from Functional Programming

#138

Often times when I read about "ideal" ways of programming, I'm curious if it's ever implemented in a production code base built by a team.

I recently did some refactoring at Google---we have a few bits of Haskell here and there---and did some similar things to what the author of the article proposed.

(Though the biggest impact of the refactoring was to remove two home-grown abstractions and a whole bunch of ad hoc transformations and replace them with the appropriate use of the very powerful, and well-understood Applicative.)

Re: Destroy All Ifs – A Perspective from Functional Programming

#139
post #117

Earlier quoted context omitted.

The title says "destroy all ifs". The author already did take the idea to the extreme himself.

It's true. Personally, I took that to be a bit tongue in cheek. I would compare it to "GOTO Considered Harmful"-- where the author wants you to imagine a world without such a technique in order to expand your abilities. (Even though there are probably edge cases where such usage is justifiable.)

The stance is rather different though - "GOTO Considered Harmful" as a phrase is both inviting a discussion and making a limited statement. "Destroy all ifs" is definitive; the argument is over at the end of the phrase and there will be no negotiation or concessions. I know that this is trivial in this case, but I think it would help discourse in the world generally if we could move away from this kind of position taking and offer our opinions more gently.

As a community we should reward more nuanced and open statements.

Re: Destroy All Ifs – A Perspective from Functional Programming

#140
post #127

Problem is, a decision has to be made somewhere about which function to pass into that "if-free" block of code. The if-like decision has just moved elsewhere. That is a win if it reduces duplication: if a lambda can be decided upon and then used in several places, that's better than making the same Boolean decision in those several places. Programs that are full of function indirection aren't necessarily easier to un…

In a language like Haskell you wouldn't want to prove the absence of recursion, but that all recursions in the program fit into a handful of patterns. (Eg 'structural-recursion' or 'tail-recursion'.) Some type systems are strong enough to put that kind of analysis / constraints directly into the language. (Haskell might already be strong enough with GADTs and other language extensions enabled.) In any case, the Adden…

That coding guideline simply rejects all recursion, even cases that are correct by inspection, or by easy proof.
Post reply on HN