Live data from Hacker News

Destroy All Ifs – A Perspective from Functional Programming

degoes.net

211–220 of 226 posts

Re: Destroy All Ifs – A Perspective from Functional Programming

#211
post #129

Earlier quoted context omitted.

Not all control-flow primitives are necessary. Eg Haskell and Scheme get by without 'while' and 'goto'. Haskell would do just fine without a built-in 'if': you can define 'if' as a function via pattern matching. Given that perspective, the article would be a call to use more expressive types than Booleans to match on---and in lots of cases not to match at all, but provide what would be the result of the match as an a…

Scheme and Haskell have other primitives that take the place of while and goto. But yes, using more expressive match types or parameters is a good idea. As for providing the result as an argument, that can be a good pattern, but isn't always practical. Note what I said in my original comment about using your own discretion.

They don't have `other primitives': they have function calls. Most languages have function calls these days.

Re: Destroy All Ifs – A Perspective from Functional Programming

#212
post #181

Earlier quoted context omitted.

Tee hee, Haskell doesn't have tail recursion (e.g. foldl takes linear space), and structural recursion in Haskell isn't guaranteed to terminate (e.g. if you're given an infinite list). If I were in charge of developing a safety critical system, and someone came to me with a proposal to write it in Haskell, I'd be very skeptical.

??? Haskell absolutely has tail recursion; foldl just evaluates non-strictly and therefore can leave thunks in memory. This is fine for e.g. reversing a cons-list. Regardless, it is tail recursive (and uses constant stack space). foldl' is also tail recursive and has strict semantics. Structural recursion can't be guaranteed to terminate in any language that supports codata unless you have some sort of totality check…

> Now, a terminating and fixed-memory subset of Haskell a la Clash would be interesting for safety critical software...

Definitely.

I something think Haskell should treat non-terminating code the same way they treat IO: only allow it in portions of the code-base that are tagged somehow.

If there's something that doesn't cause a side-effect, but the compiler doesn't know that, you can tell it with unsafePerformIO. If there's something that terminates, but the compiler doesn't know, (eg calculating the hailstone sequence for a number), there could also be a suitable escape hatch to be used with care.

Re: Destroy All Ifs – A Perspective from Functional Programming

#213
If I understood correctly, the article suggests that as a general principle you should replace your union types and case-by-case code with lambdas. I feel almost the opposite.

Article: "In functional programming, the use of lambdas allows us to propagate not merely a serialized version of our intentions, but our actual intentions!"

Counterpoint: The use of structured objects instead of black box lambdas allows us to do more than just evaluate them. For example, Redux gets a lot of power by separating JSON-like action objects from the reducer that carries out the action.

But let's take instead the article's example of case-insensitive string matching. One tricky case is that normalization can change the length of the string: we might want the german "ß" to match "SS". Sure, the lambda approach can handle that. But now suppose that we want a new function that gives the location of the first match. It should support the same case-sensitivity options (because why not?). But now there is no way to get the pre-normalization location, because we encoded our normalization as a black box function. Case-by-case code would have handled this easily.

Re: Destroy All Ifs – A Perspective from Functional Programming

#214
post #162
post #118

Earlier quoted context omitted.

Granted, I'm a mostly self-taught programmer, but I would have thought that if something appears in formal logic,[0] it should have an analog in a programming language. Even standard algorithms like quicksort[1] use conditionals. And, while I can see how massive switch statements suck, normal conditionals are common in everyday life: "If they don't have a dark roast coffee, get me a medium roast." All of which is to…

> normal conditionals are common in everyday life: "If they don't have a dark roast coffee, get me a medium roast." "They had dark roast so I got you nothing as requested." IOW, this program is either incomplete or wrong. Cf. "Get me the darkest roast they have." - ifless, concise, robust.

So if it's an undrinkable mud you are still happy, code executed perfectly :)

Re: Destroy All Ifs – A Perspective from Functional Programming

#215
post #211

Earlier quoted context omitted.

Scheme and Haskell have other primitives that take the place of while and goto. But yes, using more expressive match types or parameters is a good idea. As for providing the result as an argument, that can be a good pattern, but isn't always practical. Note what I said in my original comment about using your own discretion.

They don't have `other primitives': they have function calls. Most languages have function calls these days.

Yes, I read LTUI and LTUD. But in most languages, function calls and loops don't have the same semantics. I'll call that a different loop primitive.

Re: Destroy All Ifs – A Perspective from Functional Programming

#216
post #181

Earlier quoted context omitted.

??? Haskell absolutely has tail recursion; foldl just evaluates non-strictly and therefore can leave thunks in memory. This is fine for e.g. reversing a cons-list. Regardless, it is tail recursive (and uses constant stack space). foldl' is also tail recursive and has strict semantics. Structural recursion can't be guaranteed to terminate in any language that supports codata unless you have some sort of totality check…

The point of tail recursion is using constant space, not constant stack space (does Haskell even have a stack?) Anyways, the Haskell spec allows foldl' to use linear space just like its lazier counterparts. The fact that it uses constant space is an implementation detail of GHC. Reference: https://github.com/quchen/articles/blob/master/fbut.md#seq-d... Structural recursion always terminates in SML. Supporting infinit…

The point of tail recursion is using constant space for the environment and control flow meta info, not constant space absolutely.

Re: Destroy All Ifs – A Perspective from Functional Programming

#217
post #145

Earlier quoted context omitted.

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

Interesting. I assume they allow the special cases of tail recursion introduced by 'while', 'for' and similar constructs?

goto is banned; loops must be statically bounded.

Re: Destroy All Ifs – A Perspective from Functional Programming

#218
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…

I'd prefer to use `if let` and/or `try!()` instead of the methods here.

Re: Destroy All Ifs – A Perspective from Functional Programming

#219
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…

Oh god it's like ActionSupport came back with a vengeance.

Rust does not let you globally add things to existing stuff, so it's a very different situation than ActiveSupport, even if it may look superficially so.

Re: Destroy All Ifs – A Perspective from Functional Programming

#220
post #139

Earlier quoted context omitted.

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 ta…

"Ifs considered suboptimal" carries the spirit of Dijkstra and the general argument of the anti if folks.

That would work
Post reply on HN