Live data from Hacker News

Destroy All Ifs – A Perspective from Functional Programming

degoes.net

171–180 of 226 posts

Re: Destroy All Ifs – A Perspective from Functional Programming

#171

Earlier quoted context omitted.

The thing is that the tone of the article seems to suggest taking such an extreme: I mean, an "anti-if " campaign? There's like, only one sentence of concession near the end towards those unconvinced by the argument.

FWIW, I'm pretty unimpressed by the anti-if campaign's website. They've clearly put style over substance. It's a beautiful website, but I spent some time poking through it and I can still only guess at what exactly they're on about. It seems to be something about if-statements being bad, but beyond that it's rather a muddle. I'm trying to be charitable, though, so let's assume that the core of their idea is something…

The author is just examining a common design mistake-- there's no sin there. Many times, it's a mistake to pass in a boolean switch when you could instead pass in the predicate function itself. That's a solid example that supports the author's claim. Maybe you're not convinced, but that doesn't mean the article is completely misguided.

Re: Destroy All Ifs – A Perspective from Functional Programming

#172

Earlier quoted context omitted.

What distinction are you drawing between "first-class functions" and "function pointers"?

About the same distinction as I'd draw between an integer and a pointer to an integer.

Both function pointers and "first class functions" refer to function indirection.

In its treatment of expressions, C doesn't draw the distinction between function and pointer to function. When you call printf("foo\n"), the printf part is a primary expression which designates a function, and evaluates to a function pointer. That pointer is then dereferenced by the postfix ().

The main difference between a "first class" function and a function pointer is that a first class function carries an environment, which allows the body of the function to make references to lexically scoped names outside of the function. A function pointer carries a reference to the code only.

Re: Destroy All Ifs – A Perspective from Functional Programming

#173

This is the starter code: publish :: Bool -> IO () publish isDryRun = if isDryRun then do _ This would be nicer if you could do multiple functions with pattern matching. In Elixir this would be: @spec publish(boolean) :: any def publish(true = _isDryRun) do _ = unsafePreparePackage dryRunOptions IO.puts "Dry run completed, no errors." end def publish(false = _isDryRun) do pkg = unsafePreparePackage defaultPublishOpti…

Pattern matching is just as explicit as an if loop. In languages that implement it for null values, it is just as explicit as typing "if (foo == null)" in an imperative language. You have to think about it, and type just as much code to deal with it, as you would in a language without pattern matching. The only upside to pattern matching that I can see is that you are forced by the compiler to match all possible inpu…

The main advantage of pattern matching is that you can't forget it. If you forget to check for null, the customer complains that the program crashed. If you forget to handle the cases in a pattern, the compiler complains to you.

Re: Destroy All Ifs – A Perspective from Functional Programming

#174
post #135

Earlier quoted context omitted.

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.

Use an enum.

Re: Destroy All Ifs – A Perspective from Functional Programming

#175
post #157

Earlier quoted context omitted.

It does. This could have been written .map_err(ToString::to_string) as well. Works just fine with methods.

Why can't it be written as: .map_err(to_string) When using the lambda the type is inferred, so why should there be a need for the ToString?

If `to_string` was a function that was imported into the local namespace, you could. But since it's a method, you can't; you need to provide the trait name.

Re: Destroy All Ifs – A Perspective from Functional Programming

#176
post #14

I read everything I could find on the Anti-IF site and didn't understand what the mission is exactly. They qualify and mention they want to remove the bad and dangerous IFs, but I couldn't find examples that differentiate between bad ones and good ones -- are there good ones according to this campaign? I like using functional as much as anyone, and removing branching often does make the code clearer and remove the po…

I read everything I could find on the Anti-IF site and didn't understand what the mission is exactly. I have a similar problem, in that every time I try to understand the perspective of functional-programming advocates, I find that the authors always seem to illustrate their points with examples like this: match :: String -> Boolean -> Boolean -> String -> Bool match pattern ignoreCase globalMatch target = ... If I'm…

Well, at some point you are looking at transistors and 'if's .

How many layers above that you want to hide that fact is entirely dependant on you and the requirements of solving there problem.

I have a problem with people assuming 'their' way is there only way, and generally being oblivious about the vast variety of problems the rest of us encounter.

Re: Destroy All Ifs – A Perspective from Functional Programming

#177
post #149
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…

> I think its because until recently pattern matching and > algebraic data types (a more robust alternative to > switch statements) [...] Could you elaborate a bit on what this accomplishes, eg. pattern matching vs a "case" statement? As I've programmed in Haskell for the past year or two, I've observed exactly this change in my style of writing - that I've started to get rid of "case" statements inside function defi…

Just FYI, I asked a pretty similar question a few months ago here [1]. The main arguments for pattern matching seemed to be that:

* [at least some] compilers will check for exhaustiveness

* "Pattern matching isn't just conditional matching. It's also binding, and even some common operations. "

[1] https://news.ycombinator.com/item?id=11159321

Re: Destroy All Ifs – A Perspective from Functional Programming

#179

Earlier quoted context omitted.

Scala allows underscores, and sequential underscores refer to the next element, so you can do e.g. list(1, 2, 3, 4).reduce(_ + _) == 10

Doesn't that make the parameter anonymous, though? Can you println that _ and see the value of the current element?

Yeah, that's the tradeoff–gain the ability to work with multiple parameters but lose the ability to reuse a single one.

Re: Destroy All Ifs – A Perspective from Functional Programming

#180

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()).

It does. This could have been written .map_err(ToString::to_string) as well. Works just fine with methods.

But that's actually longer. It does look a bit better though, maybe.
Post reply on HN