Live data from Hacker News

Destroy All Ifs – A Perspective from Functional Programming

degoes.net

21–30 of 226 posts

Re: Destroy All Ifs – A Perspective from Functional Programming

#21
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.

Re: Destroy All Ifs – A Perspective from Functional Programming

#22
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.

Re: Destroy All Ifs – A Perspective from Functional Programming

#23

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 problem.

Re: Destroy All Ifs – A Perspective from Functional Programming

#24
The article seems to advocate type synonyms like the following:

    type Case = String -> String
    -- ...
    type Announcer = String -> IO String
I would argue that these are actually much worse than not having type synonyms at all.

(String -> String) functions could do anything to your query parameter and text, the type is too coarse, and the inhabitants too opaque for us to reason about them easily. Naming the type suggests the problem is solved without actually having solved it. It is like finding a hole in the ground, and covering it with leaves, so you don't have to look at it anymore. You are literally making a trap for the next person to come this way.

In an ideal world you would be able to use refinements to say that you want any (f :: String -> String) such that `toUpper . f = toUpper` but without such facilities, I think I may just settle for:

    newtype Case = CaseSensitive Bool
Sometimes, your type really does only have two inhabitants.

Re: Destroy All Ifs – A Perspective from Functional Programming

#25
Functional programmers love to emphasize how all the aspects of programming that their pet language is uniquely good at dealing with also happen to be the biggest problems in code maintenance. Is there any actual data on what the biggest problem sources are?

Re: Destroy All Ifs – A Perspective from Functional Programming

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

Rust basically offers a Monad-like API there. That's perfectly fine and a well established pattern.

That has nothing to do with primitive control flow nor is that an indication of if_weekday appearing anytime soon.

That being said having primitive control flow implemented as methods also has precedent with languages like Smalltalk or Self. That may be unusual but I don't think that's necessarily bad. I would be interested in reading about why this is bad design though.

Re: Destroy All Ifs – A Perspective from Functional Programming

#27
Bad programmers will mess any syntax restrictions/guidelines/styles we put on them. If you let them make any function were they can put launchNukes(); into doX(); then they will. though running things as a service may be the future, this launchNukes(); function is over here....safe from you.

Re: Destroy All Ifs – A Perspective from Functional Programming

#28
post #5

Define true as a lambda taking two lazy values that returns the first, and false as one that returns the second, and you can turn all booleans into lambdas with no increase in code clarity. The straw man in the post - talking about a case-sensitive matcher that selectively called one of two different functions based on a boolean - is indeed trivially converted into calling a single function passed as an argument, but…

Someone else addressed the details of your counter argument, but I'd like to respond to it generally.

It seems like every time someone writes an article on how to write better code, there are responses about how it doesn't make sense when taken to some logical extreme, or some special case, as if that invalidates the argument. (FP techniques in particular seem to provoke this.) But code design is like other design disciplines-- good techniques aren't always absolutes.

Do you really think that because the given example doesn't apply to every situation it's a 'straw man'? It is a little tiring to hear all code design advice dismissed this way.

Re: Destroy All Ifs – A Perspective from Functional Programming

#29

This whole campaigned is misguided. "Bad IFs" are a code smell, and they're being scapegoated when the real problems are management demanding that simple hackish prototypes & tests be deployed into production, management that doesn't allow time for refactoring, and poor programmers who think that "bad IFs" are good code. But the main site also doesn't do any reasonable job of defining what a "Bad IF" even is. The cru…

I think that aiming at the management of the coders and the business users is putting the emphasis in exactly the right place. Once we get to womdering if eliminating IF stmts will help, we have passed by so many opportunities for 10x value delivery.

Re: Destroy All Ifs – A Perspective from Functional Programming

#30

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…

You can do exactly the same kind of pattern matching in Haskell, but that's not at all the point of the article. It's equivalent to writing the conditional, it doesn't remove it.

    publish :: Bool -> IO ()
    publish True =
      unsafePreparePackage dryRunOptions >>
        putStrLn "Dry run completed, no errors."
    publish False = do
      pkg 
Post reply on HN