He won Powerball's $314M jackpot. It ruined his life - <AUTHOR> https://www.washingtonpost.com/history/2018/10/24/jack-whittaker-powerball-lottery-winners-life-was-ruined-after-m-jackpot/ <comment><USER2> This story is quite common. The obvious conclusion is that a large infusion of money can ruin someone. But it occurred to me recently to wonder if there's a selection effect where people who are bad with money are far more likely to buy lottery tickets. People who are bad with money can waste whatever quantity they are given. Someone like that isn't going to get a lot happier with an infusion of cash. Or rather they would with a gradual infusion over time coupled with some training and discipline. 3 things which are deliberately avoided in the framing of the lottery.

<comment><USER3> The interesting part is that lotteries are investment schemes of a sort and designed for gradual payouts more akin to an annuity. The jackpot numbers always include a disclaimer that that would be the total winnings over the lifetime of the payout of that "investment product": immediate payouts are considerably smaller and not just because they involve more taxes. (Obviously it is in the lotto's favor to often spin it as entirely taxes and fees, rather than admitting that it's an "investment" product that they "sell" to "buyers" where the large dollar figures are based on a time-value-of-money calculation.)

The number of contestants that take the lump sum up front instead of treating it like an annuity to supplement their lifestyle over time is staggering, and also indeed another likely indicator of the selection effect that the people most likely to play the lottery are the least likely to have good investment advice in their lives.

<comment><USER4> Taking the lump sum is not at all indicative of a lack of good investment advice. Going with the installment payments is equivalent to taking the lump sum and then investing it all in US treasury bonds. That's an extraordinarily conservative investment strategy and most investment advisors would recommend something more aggressive.

<comment><USER5> Getting a surprise $100M is different from managing your portfolio. Aggressive means easy to lose it all due to ignorance or fraud. Getting a dozen mulligans via installments is good insurance against losing it all.

<comment><USER4> > Getting a surprise $100M is different from managing your portfolio.

It's really not that different. All of the advice out there concerning how to prudently manage a portfolio of $100K applies pretty well to $100M. Going up to the $100M opens up some additional options (private equity, hedge funds, venture capital, real estate) and involves some additional taxes (estate/gift taxes), but you could do a lot worse with your $100M than sticking 60% in low cost equity index funds and 40% in low cost bond index funds and ignoring alternatives and tax optimization.

> Aggressive means easy to lose it all due to ignorance or fraud.

More aggressive than ultra-conservative does not mean aggressive in an absolute sense.

</comment></comment></comment></comment></comment><comment><USER6> There's a old reddit post about how to win the lottery well. It's one of the most fascinating things I've read. [https://np.reddit.com/r/AskReddit/comments/24vo34/whats_the_...](https://np.reddit.com/r/AskReddit/comments/24vo34/whats_the_happiest_5word_sentence_you_could_hear/chb4v05/)

<comment><USER7> Looks like it's based off [https://www.ar15.com/forums/general/-/5-749519/?page=1](https://www.ar15.com/forums/general/-/5-749519/?page=1)

<comment><USER8> Interesting to see another user here cite Arfcom.

First the chans began to merge with Arfcom GD, and now HN is becoming more connected. I'm interested to see where this goes.

</comment></comment></comment><comment><USER9> Interesting. I wonder how prevalent this sort of thing is? I mean, even small populations of people will contain a ne'er do well, or a gambler or something. Does the prevalence of lottery winners that screw up match the general population's prevalence of individuals who screw up?

Without some indication like the above, it's hard to take the WaPo seriously on this.

<comment><USER10> I'd guess the reporting is also biased, there is not much to tell in the cases of people who have won and just lead a stable life afterwards.

</comment></comment><comment><USER11> About 30 years ago, I read a book about lottery winners and the stories read very similar to Mr. Whitaker's, back when a mere million dollar payout was a big deal.

Though it's possible the book had a selection bias - because who would read the stories that ended happily ever after?

I'm not sure regular schmoes can avoid problems with large sums of money because we're not used to dealing with wealth or the problems it attracts. Rock stars, pro athletes, and even heirs to family fortunes have similar problems.

Given the likelihood of winning, I've already spent too much time thinking about what life modifications might be needed but here goes --

1) If you know or can access someone who has tons of money (e.g. Bill Gates), ask them. Though people such as Bill Gates probably have most of their wealth in investments, not cash.

2) Get a second address or at least access to a place under someone else's name. Assume your driver's license info will become public knowledge.

3) A couple of lawyers on retainer is good, at least one who specializes in defending against frivolous lawsuits. Maybe one who specializes in such lawsuits, just to knock them out of the pool of possible attorneys who would come after you. I heard Michael Avenatti might be available.

4) Having a friend or two in the police might help, they can find people willing to pull security details. The key phrases here are POST-certified, sworn officers. I'm not as big on hiring military-grade "operators" but maybe if you find yourself dealing with kidnappers or other hard-core types...

5) I prefer lump sum, because governments have a reputation for altering plans. Not to say a government wouldn't just confiscate one's holdings, but it's usually easier to not give something than to take it back.

6) If you are a man, seriously consider a vasectomy. That won't stop the paternity suits but you'll sleep a bit easier. Apparently celebs have doppelgangers who bed women on the reputation of others. That may be a harder scam to pull off in the age of smartphones.

</comment><comment><USER12> In most states, the biggest issue is still the one of anonymity.

I wonder if there's a way around that by selling/auctioning off your winning ticket to somebody who's already famous and, say, a billionaire at a discount.

<comment><USER13> I don't know why there hasn't been a lawsuit about this yet. Maybe there will be at the Federal level. Since some states allow anonymity and as such the powerball agreements do then it seems unreasonable for states to require public disclosure.

<comment><USER14> There has been at least one recent lawsuit

[https://money.cnn.com/2018/03/12/news/powerball-winner- anony...](https://money.cnn.com/2018/03/12/news/powerball-winner- anonymous/index.html)

<comment><USER12> That was a different situation though: NH allows trusts to claim the ticket, but only if the ticket is signed by the trust representatives.

The woman in question had already signed the ticket in her own name before setting up the trust.

Most states don't allow trusts to claim a ticket at all.

</comment></comment></comment></comment><comment><USER15> Of course, what's true of individuals, is true of societies, too. Getting rich quick (particularly without effort) brings out the worst. Look a Saudi funding for 911 and much other mischief they've funded, for example.

But this may be true of Western nations in general as wealth accelerates; and the increasing Gini coefficient in the U.S. may be just one more sad symptom of too much wealth, not too little. The U.S. won the techprogress lottery, and doing so seems only to have amped up political craziness, drug use and inequality.</comment>


Game of Trees (Got): A Version Control System for OpenBSD - <AUTHOR> https://gameoftrees.org <comment><USER2> To wit: OpenBSD is keeping the on-disk repo format the same, but they're replacing the GPLv2 Git codebase with a smaller¹, tighter¹, less buggy¹, more secure¹ BSD-licensed workalike. That's what they do; they drink soda, and they rewrite things. [https://gameoftrees.org/goals.html](https://gameoftrees.org/goals.html)

[1] YMMV. It is known.

</comment><comment><AUTHOR> Short blurb:

> _Got uses Git repositories to store versioned data. At present, Got supports > local version control operations only. Git can be used for any functionality > which has not yet been implemented in Got. It will always remain possible to > work with both Got and Git on the same repository._

Manual page:

* [https://gameoftrees.org/got.1.html](https://gameoftrees.org/got.1.html)</comment>


Reasons for using Golang - <AUTHOR> http://programmers.stackexchange.com/questions/82179/examples-of-beautiful-go/82307#82307 <comment><USER2> The only reason to use Go is if you've fallen victim to the Google hype. There's no reason to use a slightly less shitty version of C with most of its fundamental problems (shared mutable state, nullability by default...) fully intact but orders of magnitude fewer programmers when you can _just use C_.

<comment><USER3> > fundamental problems (shared mutable state, nullability by default...)

Those aren't the "fundamental problems of C", those are the _reasons people use C in the first place_. The point of "systems languages" like C and Go is that they directly expose a (standardized interface to) the Von Neumann architecture your computer actually implements, which allows for arbitrary references to memory that may be uninitialized, multiply-aliased, etc. This is what allows for the efficient implementation of such things as garbage collectors, process schedulers, virtual memory managers, IPC libraries, network stacks, and so forth, that the runtimes for higher-level languages rely upon as fundamental abstractions.

So, given the assumption that such code is necessary to write, why shouldn't we try to have a better language to write it in than C? I'm not suggesting that Go is such a language, but your argument seems to be that it's pointless to try to do better than C (because every language, no matter how good, starts with no one using it, and thus necessarily will have fewer programmers than C does.)

<comment><USER4> Well, no, the state that's shared, is shared across goroutines in Go, or across Posix threads in C. Those are not directly exposing the machine, those are exposing a particular type of abstract machine over the actual machine. Contrast Erlang processes which are built on the same machine but have different assumptions (message passing by copying, no shared state)

In fact there are hardware models that fit Erlang better, such as non-cache- coherent NUMA. So from a certain perspective, it's not that C is low level, it's that the CPU was designed to execute C. And the CPU is anyhow general enough to be used in non-C-like ways.

I personally think Go missed a trick when it didn't require channel data to be provably impossible to alias across goroutines. (It could be immutable, pass- by-value, or "unique" such that aliasing is disallowed.)

As for nulls, Go actually doesn't really have them, the poster above is mistaken - Go has zeroed values, and you are encouraged to make them valid- but-empty. That includes zeroed pointers.

<comment><USER2> _Go has zeroed values, and you are encouraged to make them valid-but-empty. That includes zeroed pointers._

Is there a material difference between that and null? I don't care what I'm "encouraged" to do -- does the language force you to opt in to null?

<comment><USER4> <http://golang.org/doc/go_spec.html#The_zero_value>

Yes if you're using pointer-like things, but at least in Go it's an unsurprising thing, all uninitialized data is zeroed. And Go permits you to work with by-value structs and arrays if you want.

<comment><USER2>
      t.next == nil

I don't give a fuck whether it's called null or 0 or nil or whatever, or whether it's amazing or surprising or shocking. Every single pointer has null as a possible value, which means Go suffers from what I think is the biggest possible mistake a (non-scripting) programming language could make (and I'm not alone -- Tony Hoare thinks the same). The worst thing about all this is that we already _have_ a well-known and well-studied solution in the Maybe monad, yet the Go designers buried their collective heads in the sand here.

<comment><USER4> On the upside, Go does not suffer from the common Java anti pattern of returning a semantically meaningful null. Its multiple return means that while it can't return "Maybe Foo", it usually returns something like "Either Error Foo", with the multiple assignment taking the place of a rather primitive pattern match. Also a go function is typically structured like a primitive Either monad - it returns with an error immediately if it gets one, or else it returns from the end with a value.

<comment><USER2> Tons of functions in most imperative languages are structured in an early- return-on-error style, with exceptions simply being a special case of that. That is neither novel nor uncommon.

<comment><USER4> But not with multiple return where (as an idiomatic design pattern) the _same_ error object is passed up through the call stack until something decides to handle it, which is what the Either monad does. (And unlike exceptions, the Go way and the Either monad are both explicit, there are no unmarked returns.)

The C way with single return means that it's generally impossible to just forward the same error object - the caller has a different type from the callee, so where one returns null another has to return -1, and so forth.</comment></comment></comment></comment></comment></comment></comment></comment></comment>


A List of Bad Words from Disqus - <AUTHOR> http://mediacdn.disqus.com/1362527340/sample-badwords.txt

<comment><USER2> Before everyone gets their pitchforks out, why don't we look at the URL and see that it has the "sample-" in it? Meaning that this is an example of words that can be filtered. It IS NOT a list of words Disqus automatically filters.

There is a filter tab in the Disqus admin area, one of those tabs is "filter," here is the text around below the restricted words input box:

"Separate words with commas. You may use .* (dot asterisk) as wildcard, but be careful not to be too aggressive. For example, s.*ck will match suck, but also sock and stack. Words must be at least 3 characters in length.

Here is a sample list of restricted words[1]."

[1] <http://mediacdn.disqus.com/1362527340/sample-badwords.txt>

<comment><AUTHOR> Thanks for a better clarification than I provided!

</comment></comment><comment><USER3> And that's just one commit message!

</comment><comment><USER4> Why is "poop" there?! I doubt think think anyone is going to teach their children to say "Mother, I need to excrete feces and deposit them into the toilet."

<comment><USER5> You better deposit them in the toilet!

</comment></comment><comment><USER6> Flange? Feeling old right about now

<comment><USER7> How is one supposed to discuss groups of baboons without "flange"? "Whoop" is allowed, so I guess it's okay to talk about gorillas. That's speciesist!

</comment></comment><comment><USER8> <http://slurtracker.com>

<comment><USER9> Wow, the amount of homophobia on twitter is staggering...

</comment></comment><comment><USER10> I enjoy that they are all "bad words"... except for the "viagra" variations. As if they just couldn't help putting that in to filter too.

<comment><USER11> Maybe it's being used as a spam filter too?

<comment><USER12> Then it should be called "spam words list"

</comment></comment></comment><comment><USER13> How do we know this is the list that's used? It looks like you can't write "door knob".

Does this really help? Or is this a filter that a site can choose to enable, to claim they did something "for the kids"?

</comment><comment><USER14> Daniel from Disqus here. We have a list of common restricted "obscenities" used on Disqus-powered sites. That list is provided there for convenience.

</comment><comment><USER15> So you can't post any of these words? I think a community moderated system is much better , because you don't to use any of these words to be offensive

<comment><AUTHOR> No, this is all optional. From the site owner admin panel in disqus you can add a custom list of words that you want to Block, and you can also add wildcards (.*) characters. I just thought this was a very funny and succinct list with a lot of creative loophole words in there as well.

</comment></comment><comment><USER16> Orgasm is a bad word?? While they are electing the new pope, the conclave will be patting themselves on the back for a job well done on that one.

<comment><AUTHOR> That's got nothin on "Willies", most 5 year-olds would say that without turning a head.

<comment><USER17> At least it will prevent people from spelling Bruce Willis wrong.

</comment></comment></comment><comment><USER18> I guess that explains why my comment that mentioned C. A. R. Hoare on a programming blog that uses Disqus never showed up...

</comment><comment><USER19> Twunt? Well, I guess you learn something new every day.

</comment><comment><USER20> did anyone else just look up what "smegma" means?

<comment><USER21> I learnt that one from Red Dwarf: <http://en.wikipedia.org/wiki/List_of_Red_Dwarf_concepts#Smeg>

<comment><USER17> "There has been some speculation that the name is related to the word smegma; however, this has been denied by the writers"

</comment></comment></comment><comment><USER22> That's it?

</comment><comment><USER23> Is this a filter list? Isn't a regex faster for this kind of thing, especially with terms that are just plural versions of other terms?

<comment><USER24> I imagine it's more complex than that. If not, I'd hate to be a door knob company.

These words are probably used to score messages based on how likely they are to be bad.</comment></comment>


Matt Tanase (a founder of Slicehost) on Rackspace's decision to kill Slicehost - <AUTHOR> http://thestartupfoundry.com/2011/05/05/matt-tanase-a-founder-of-slicehost-on-rackspaces-decision-to-kill-slicehost/

<comment><USER2> I'm Matt if anyone has any questions or comments let me know firstname.lastname@example.com

<comment><USER3> Thanks for building the product that taught me how to set up and admin a Linux box. I wouldn't know a tenth of what I know now without the Slicehost tutorials and the ability to have my own little sandbox on the web.

<comment><USER4> I have to chime in here to praise the slicehost tutorials. They are absolutely the best resource.

</comment></comment></comment><comment><USER5> Thanks for Slicehost, I ran a server there for quite a while before it was bought and it was great. Devstructure looks like good cleverness as well!</comment>


Cloudflare advertisement on sites that are down - <AUTHOR> http://poac.com/ If the site comes back up the ad will disappear.<p>If that happens here is what it said:<p>"This page http://poac.com is currently offline. However because the site uses CloudFlare's Always Online (TM) you can continue to surf a snapshot of the site. We will keep checking in the background and, as soon as the site comes back up, you will automatically be served the live version. Always Online (tm) is powered by (link) Cloudflare. [hide this alert] <comment><AUTHOR> If the site comes back up the ad will disappear.

If that happens here is what it said:

"This page [http://poac.com](http://poac.com) is currently offline. However because the site uses CloudFlare's Always Online (TM) you can continue to surf a snapshot of the site. We will keep checking in the background and, as soon as the site comes back up, you will automatically be served the live version. Always Online (tm) is powered by (link) Cloudflare. [hide this alert]</comment>


Destroy All Ifs – A Perspective from Functional Programming - <AUTHOR> http://degoes.net/articles/destroy-all-ifs <comment><USER3> 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 - <USER2> indeed trivially converted into calling a single function passed as an argument, but it's hard to say that it's an improvement. Now the knowledge of how the comparison is done is inlined at every call point, and if you want to change the mechanism of comparison (perhaps introduce locale sensitive comparison), you need to change a lot more code.

That's one of the downsides of over-abstraction and over-generalization: instead of a tool, a library gives you a box of kit components and you have to assemble the tool yourself. Sure, it might be more flexible, but sometimes you want just the tool, without needing to understand how it's put together. And a good tool for a single purpose is usually surprisingly better than a multi- tool gizmo. If you have a lot of need for different tools that have similar substructure, then compromises make more sense.

This is just another case of the tradeoff between abstraction and concreteness, and as usual, context, taste and the experience of the maintainers (i.e. go with what other people are most likely to be familiar with) matters more than any absolute dictum.

<comment><USER4> 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.

<comment><USER5> 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.

<comment><USER6> 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 coherent. I'm guessing it's really about something I do think is an important point: How inversion of control is a design pattern that lets you create code that's much easier to manage, because it greatly limits the extent to which certain kinds of decisions need to be federated throughout the codebase.

If that's the case, then real sin (and the article author's) is mistaking if statements for the problem. Conditional branching is not a problem; I think most of us can agree it's an essential operation. The real problem they should be after is poor encapsulation. Where if statements come into it is that, if you've got badly architected code with poor encapsulation, one of the symptoms you'll see is that there will be a proliferation of if-statements that crop up all throughout the code. Every single frobinator will need to stop and check whether the widget it's operating on is a whosit or a whatsit before it can take any sort of action whatsoever. Lord help us if we ever try to introduce wheresits into the system; we'll have to go modify 50 different files so we can replace all those if-statements with switch statements.

It's probably nowhere near as fun to write an article that advocates a high level design methodology as it is to write an article that makes a bold contrarian claim like "If statements bad", though.

<comment><USER7> You are totally right.

As an example, long if/else chains that check state can mean that you need another object, or another virtual function, or some other niblet of orchestration.

Likewise, I'm not really impressed by the anti-if campaign. At some point, abstractions cause the exact same problem they were designed to solve, and produce code that is difficult to reason about or change.

</comment></comment></comment></comment></comment><comment><USER8> I'm surprised that the article and none of the comments so far mentioned the "Expression Problem": [http://c2.com/cgi/wiki?ExpressionProblem](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-statements (or switch or pattern matching ...) then its hard to add new "classes" but its very easy to add new "methods".

I'm a bit disappointed that this isn't totally common knowledge by now. I think its because until recently pattern matching and algebraic data types (a more robust alternative to switch statements) were a niche functional programming feature and because "expression problem" is not a very catchy name.

<comment> jake-low I was familiar with the problem but didn't have a name for it; thanks for providing me with one.

What kind of work has there been on creating programming paradigms that make it easy to both add new types and new methods? Is it a CAP-theorem-type problem where every solution is a trade-off, or is there a way to have your cake and eat it too?

<comment><USER9> There are languages (libraries) that solve it. For reference, check Clojure's multimethods and OCaml's polymorphic variants.

<comment><USER10> The tradeoff is that techniques like multimethods significantly weaken the contract that people normally expect from methods/classes.

For example, if I'm writing a normal Java class, I know where I go to find methods dealing specifically with instances Foo (namely Foo and its children and direct users); with multimethods, it's more likely that there is some multimethod out there in an unrelated class that looks for instances of Foo.

<comment><USER11> Good tooling (think something along the lines of Hoogle) can help here.

</comment></comment></comment></comment></comment><comment><USER12> 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 understand than ones which are full of boolean conditions and if.

The call graph is harder to trace. What does this call? Oh, it calls something passed in as an argument. Now you have to know what calls here if you want to know what is called from here.

A few days ago, there was this HN submission: [https://news.ycombinator.com/item?id=12092107](https://news.ycombinator.com/item?id=12092107) "The Power of Ten – Rules for Developing Safety Critical Code"

One of the rules is: no function pointers. Rationale: _Function pointers, similarly, can seriously restrict the types of checks that can be performed by static analyzers and should only be used if there is a strong justification for their use, and ideally alternate means are provided to assist tool-based checkers determine flow of control and function call hierarchies. For instance, if function pointers are used, it can become impossible for a tool to prove absence of recursion, so alternate guarantees would have to be provided to make up for this loss in analytical capabilities._

<comment><USER11> 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 Addendum at the end of the blog post provide a different perspective on the problem you mentioned.

<comment><USER13> 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.

<comment><USER14> ??? 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 checker (e.g. via a monotonically structurally decreasing requirement imposed at the type or value level). I don't think any mainstream language supports this out of the box. Liquid Haskell does offer this, though.

I agree that standard Haskell is inappropriate for safety critical software, but only because it allows dynamic allocation. Any program using dynamic allocation is probably unsuitable for safety critical software. Now, a terminating and fixed-memory subset of Haskell a la Clash would be interesting for safety critical software...

<comment><USER13> 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...](https://github.com/quchen/articles/blob/master/fbut.md#seq- does-not-specify-an-evaluation-order)

Structural recursion always terminates in SML. Supporting infinite/cyclic values in algebraic data types is a misfeature, and they are trivial to rule out without using a totality checker. Heck, I can implement a guaranteed finite linked list in Java :-)

I think something like MLKit would be a more promising start for implementing a safety critical system. Tail and structural recursion actually work there, and it statically replaces most uses of GC with region inference. Though it's still a very long shot, I'd prefer something more proven.

<comment><USER14> Tail recursion can't use constant space if it's strictly generating another data structure of the same size. That doesn't even make sense.

Interesting fact about foldl'. Regardless, in practice it is strict and tail recursive. As I mentioned earlier, this does not mean the same thing as constant space unless the reduction function returns a fixed size result.

Yes, you can guarantee that a linked list in Java is finite because Java does not support codata.

Haskell's tail call recursion is also often optimized to be allocation-free, unless, again, it is generating some data structure.

<comment><USER11> > Yes, you can guarantee that a linked list in Java is finite because Java > does not support codata.

What about another thread running that keeps generating pieces to the end of the linked list? (No problem, with mutation.)

<comment><USER13> To prevent these and similar "what abouts", here's an implementation of a guaranteed finite linked list in Java.

        class LinkedList<T> {
          public final T value;
          public final LinkedList<T> next;
          public LinkedList(T value, LinkedList<T> next) {
            this.value = value;
            this.next = next;
          }
        }

Here's how you construct it:

        LinkedList<String> myList =
          new LinkedList("Hello",
            new LinkedList("World", null));

Here's how you iterate over it in constant space:

        while (myList != null) {
          System.out.println(myList.value);
          myList = myList.next;
        }

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER15> This is, as many commenters have noted, just another overzealous programming doctrine. Just like 'GOTO considered harmful.'

Here's the deal: if is a flow control primitive. Just like goto and while. If (heh) that primitive isn't high-level enough to handle the problem you are facing, it is incumbent upon you as a programmer to use another, higher level construct. That construct may be pattern matching, it may be polymorphism (or any other form of type-based dynamic dispatch). It may be a function that wraps a complex chain of repeated logic, and is handed lambdas to execute based upon the result. It may, as in the article given here, be a funtion that is handed lambdas which apply or do not apply the transformation described.

The point is, there are many branch constructs, or features that can be used as branch constructs, in most modern programming languages. Use the one that fits your situation. And if that situation isn't a that complex, that construct may be if.

Fizzbuzz using guards is the most clean and modifiable fizzbuzz that I've seen in Haskell.

Although now that I think about it, if you provide a function with a list of numbers...

<comment><USER11> 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 argument to the function.

<comment><USER15> 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.

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

<comment><USER15> 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.

<comment><USER11> For C, this seems to be implementation defined.

(At least for C as encountered in the wild, I don't know about C the standard.)

Most modern C compilers support tail call optimization.

I don't know about `most languages'. Eg I know Java on the JVM doesn't do tail call optimization. Lots of languages probably do not require TCO of their implementations, though.

</comment></comment></comment></comment></comment></comment><comment> white-flame 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 crux of the matter is that programmers need time to craft the details of a project to avoid or correct technical debt. These sort of reactions just point out one tiny portion of technical debt itself and doesn't solve any fundamental problems at all.

(and yeah, I known I'm ranting against the Anti-IF campaign, not the particular take on the linked site. But this article just seems to parameterize the exact same parameters that are branched on anyway.)

<comment><USER16> 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.

<comment><USER6> The "technical debt" metaphor gets so much better if you take the analogy more literally than most people do. Like for financial debt, the optimal amount is not necessarily zero. Oftentimes taking on or carrying debt allows you to generate more profit than you could by avoiding it or paying it down.

That said, most places I've worked manage it poorly. Few people really understand that, just like financial debt, it's something that needs to be taken on and managed in a mindful and deliberate manner.

<comment><USER11> Also, if you do take the finance metaphor, going into debt is not good by itself. It's the investments you make with that debt that are good, and potentially outweigh the burden of debt. (And can be cheaper than equity financing.)

Going back to programming: debt-fuelled programming should buy you something, eg speed to market, and is not a good in itself.

</comment></comment></comment></comment><comment><USER17> 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::<i32>().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 programming, either; those expressions can have side effects.

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

<comment><USER19> 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 }

<comment><USER20> Scala allows underscores, and sequential underscores refer to the next element, so you can do e.g.

        list(1, 2, 3, 4).reduce(_ + _) == 10

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

<comment><USER21> Use a function that prints then returns its parameter:

      list(1, 2, 3, 4).reduce{print(_) + _} == 10

Use it if you or your language hasn't defined such a function:

      list(1, 2, 3, 4).reduce{it:= _; println(it); it + _} == 10

In fact, any name for it will do.

</comment></comment></comment></comment></comment></comment><comment><USER22> This just seems to obscure the logic. Not unlike how polymorphism can make code flow harder to read, though feel more clever.

There is a place for it - like when you're trying to express a set of logic that will be guarded by the same condition, but always at the cost of some complexity.

A set of conditionals is probably the most obvious way to express branching.

<comment><USER23> Try it before you knock it. I might have said something similar before getting into Haskell, but now I'm nodding along happily. Dealing in meaningful data types with small composable functions is very pleasant for me now.

<comment><USER24> > _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](https://news.ycombinator.com/item?id=12108138)

<comment><USER23> 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!

<comment><USER11> 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.

<comment><USER25> Your first point is actually something I really like about Python's API design: in general, methods operating on collections either mutate the collection /or/ they return it. So it's clear at the point of use whether you're dealing with the same object or a new one.

This is something that bugs me about the fluent builder pattern in Java -- continuing to return `this` until suddenly you don't any more, and you can't re-use 'intermediate' values because they're actually all the same object.

<comment><USER11> Sure. I'd just like to have a nice set of operations to manipulate dicts that don't mutate and return the result, too.

</comment></comment></comment></comment></comment></comment></comment><comment><USER26> I recommend Bob Harper's essay on "boolean blindness": [https://existentialtype.wordpress.com/2011/03/15/boolean- bli...](https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/)

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.

<comment><USER27> 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.

<comment><USER11> 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?)

<comment><USER28> The difference, in terms of type theory, is that a tuple is a product type [1] but a type representing multiple possible return values (to represent different outcomes) would be encoded using a sum type [2].

[1] [https://en.wikipedia.org/wiki/Product_type](https://en.wikipedia.org/wiki/Product_type)

[2] [https://en.wikipedia.org/wiki/Tagged_union](https://en.wikipedia.org/wiki/Tagged_union)

<comment><USER11> I don't think eg Go uses a sum type:

[https://gobyexample.com/multiple-return- values](https://gobyexample.com/multiple-return-values)

Typically they use product types to simulate sum types.

</comment></comment></comment></comment></comment><comment><USER29> 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.

<comment><USER30> Me too. Particularly because every programmer has their own idea of what a "right"/ideal style of programming is. Here, apparently, we must not use conditionals.

The more I write code the more I realize that the entire purpose of the code is to have some effect on reality, and the more reliably it can do this, the better the code. I find I code a lot better without design principles, because trying to remember which patterns are "good" and "bad" just obscures the attention I would have used to look at the code and sense whether something would work in this particular situation.

<comment><USER31> Not functional code though. The aim of functional code is to be side-effect free, and affecting reality really gets in the way of that.

/snark, but articles like this really do fall into that trap...

<comment><USER30> I know you're making a joke, so I'm not writing this to correct you, but I'd like to point out that Haskell/pure FP is different not because it denies affecting reality, but because it only offers a one-way interface to affecting reality: it allows you to alter values in reality using pure functions, but it denies you the ability to "pull in" values from reality, into your pure functions.

This paradigm is powerful because it accurately reflects how our universe works: it is possible for a thought to affect reality (through a human being acting on it), but it is not possible to "pull in" an object from reality, into your mind. The only way to form a thought about something is to look at that thing, and try to construct - in your mind - a thought that reflects certain properties of the thing you're looking at. You can't "pull" that thing from reality into your mind, thus creating a thought. No such interface exists in this universe, as far as I'm aware.

It is, however, very possible for a human being to choose to act on a thought, thereby causing the thought to have a side effect. The analog to this in Haskell is applying a pure function to a value in IO. The function is pure, but we can use it to alter a value that resides in IO (reality). Similarly, a thought, in and of itself, does not affect reality (it is pure); it requires a human being to act on it - "apply it to reality" \- in order for it to have an effect.

In short: Haskell allows your program to alter reality, but it does not allow reality to alter your program.

</comment></comment></comment></comment><comment><USER32> 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 potential for mistakes.

But I admit I have a hard time with suggesting people prefer a lambda to an IF, or to not ever use an IF. A lambda is, both complexity wise, and performance wise, _much_ heavier than an IF. And isn't is just as bad to abstract conditionals before any abstractions are actually called for?

<comment><USER33> _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 already literate in Haskell or Clojure or Brainfuck or whatever godawful language that is, then chances are, I'm already familiar with the strengths of the functional approach, and I'm consequently not part of the audience that the author is supposedly trying to reach.

So: are there any good pages or articles that argue for for functional programming where the examples can be followed by a traditional C/C++ programmer, or by someone who otherwise hasn't already drunk the functional Kool-Aid?

<comment><USER34> The problem's not on your end -- a lot of these blogs are just junk, probably the vast majority of ones that fall under "advocacy". As far as I can tell, the author's objection to conditionals is based on a misunderstanding of a different blog post[0]. It's nonsense.

Really understanding where FP is coming from requires an introduction to programming language semantics[1]. Interesting stuff, but not immediately useful to a working C programmer.

[0] [https://existentialtype.wordpress.com/2011/03/15/boolean- bli...](https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/)

[1] [http://www.cs.cmu.edu/~rwh/pfpl.html](http://www.cs.cmu.edu/~rwh/pfpl.html)

</comment></comment></comment><comment><USER35> I tried to ask the author the follow: (kept getting deleted as spam). Perhaps he will see it here but its unlikely due to the fact there are many comments as it is.

Hi John,

Are you familiar with Jackson Structured Programming?

[https://en.wikipedia.org/wiki/Jackson_structured_programming](https://en.wikipedia.org/wiki/Jackson_structured_programming)

Notice how the focus in on using control flows that are derived from the structure of the data being processed and the processed data. Notice how the JSP derived solution in the Wikipedia example lack if-statements.

Pattern matching allows ones to map control flow to the structure of data. What are your thoughts on that? I think inversion of control has other benefits but I don't think it has much to do with elimination of `if` conditionals, the pattern matching does that.

Also, I noticed one thing:

In the article you mention `doX :: State -> IO ()` as being called for its value and suggest that if you ignore the value the function call has no effect. Isn't it the case that a function of that type usually denotes that one is calling the function for its effect and not for any return value? Its value is just an unevaluated `IO ()`.

<comment><USER36> 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".

<comment><USER35> 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)

<comment><USER11> 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.

</comment></comment></comment></comment><comment><USER37> The author seems to ignore the fact that passing lambdas like this merely changes where the IF or SWITCH statement is made. I can agree that passing functions instead of booleans is better and more general. But pretending that IF/SWITCH are thus avoided, is delusional.

For instance, at some point there will be a decision made whether the string matching must be case sensitive or not. If the program can do both at runtime, the IF will be, perhaps, in the main (or equiv.).

<comment><AUTHOR> Indeed, that's the whole point of inversion of control, is pulling the control out of the caller and into the callee. That's the primary reasoning benefit of functional programming.

<comment><USER38> I see no benefit to that. It makes more work for the caller. I want that function to do something for me and I want the leadt amount of unnecessary work on my side. Just like a good boss who delegates.

<comment><AUTHOR> That's why not everyone's a functional programmer. :)

</comment></comment></comment></comment><comment><USER39> Why don't we just treat this like writing?

Good writing has one clear imperative: communicate meaningfully the intent of the author to the reader. Good code is no different; it is merely expressive writing in a different language, with, perhaps, greater constraint on its intent.

Some people make up rules like "don't use adverbs", or "don't split infinitives", in an effort to write better. But this doesn't necessarily produce good writing; sometimes an adverb is just what you need.

The same is true of code. These are useful things to think about, but "destroy all ifs" is akin to "never use a conjunction".

<comment><USER40> I get what you're saying, but that's definitely not what good writing means in the context of, say, poetry, or literary fiction. Programming is best compared to technical writing or cookbooks, I think.

I realize this is one of those irritating "actually," replies, but what can I say, I'm sensitive about this topic. =)

</comment></comment><comment><USER41> 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.

</comment><comment><USER42> The first problem is that the "match" function is considered in the first place. It's too general. It should only be used in higher order constructs where its flexibility is actually needed.

Second: The enum based refractor is actually valuable and fine IMO. If you need string functions, stop there.

Now, shipping control flow as a library is a cool feature of Haskell. But, if those arguments are turned into functions, the match function itself isn't needed! It just applies the first argument to arguments 3 and 4, then passes them to the second argument.

match :: (a -> b) -> (b -> b -> Bool) -> a -> b match case sub needle haystack = sub (case needle) (case haystack)

Does that even need to be a function? Perhaps. But if so, it's typed in a and b and functions thereof, and no longer a "string" function at all. And, honestly, why are you writing that function?

Typing it out where you need it is typically less mental impact, because I don't need to worry about the implementation of a fifth symbol named "match."

sub (case needle) (case haystack)

</comment><comment><USER43> Isn't this exactly the Smalltalk way? In ST what looks like if-statements actually are messages passed to instances of Boolean, with lambdas (in Smalltalk: BlockClosures) as argument. The boolean then makes the decision whether it will evaluate the lambda or not.

</comment><comment><USER44> When I read things like "anti-if" I recall this brilliant illustration that I saw several years ago - [http://blog.crisp.se/henrikkniberg/images/ToolWrongVsWrongTo...](http://blog.crisp.se/henrikkniberg/images/ToolWrongVsWrongTool.png)

</comment><comment><USER45> The inversion of control flow from called to calling function is an interesting way to describe (part of) functional programming style. I hadn't thought of that this way, even though I use it for quite some time.

</comment><comment><USER46> General principle: for every possible refactoring, the opposite refactoring is sometimes a good idea.

So, yes, replacing booleans with a callback is sometimes a good idea. But in other situations, replacing a callback with a simple booleans might also be a good idea.

Also, advice like this is often language-specific. In languages whose functions support named parameters, boolean flags are easy to use and easy to read. If you only have positional parameters, it's more error-prone, so you might want to pass arguments using enums or inside a struct instead.

</comment><comment><USER47> Someone found a hammer, and now everything looks like thumbs

</comment><comment><USER48> tl;dr: prefer callback hell instead of straight forward ifs and somehow that's progress.

<comment><USER49> Yeah, and the true fun starts when you try to debug it. Debugging streams in java is nightmare compared to debugging the same logic written in a simple foreach loop with a bunch of IFs.

</comment></comment><comment><USER50> The idea that functional programming is a type of inversion of control reminds me of similar idea I had, when comparing OOP and FP.

In OOP, you encapsulate data into objects and then pass those around. The data themselves are invisible, they only have interface of methods that you can apply on them. So methods receive data as package on which they can call methods.

In FP, in contrast, the data are naked. But instead of sending them out to functions and getting them back, the reference frame is sort of changed; now the data stays at the function but what is passed around is the type of processing (another functions) you want to do with them.

For example, when doing sort; in OOP, we encapsulate the sortable things into objects that have compare interface, and let the sort method act on those objects. So at the time sort method is called, the data are prepared to be compared. In FP, the sort function takes both comparison function as an argument, together with the data of proper type; thus you can also look at it as that the generic sort function gets passed back into the caller. In other words, in FP, the data types _are_ the interfaces.

So it is somewhat dual, like a different reference frame in physics.

The FP approach reminds me of Unix pipes, which are very composable. It stands on the principle that the data are the interface surface (inputs and outputs from small programs are well defined, or rather easy to understand), and these naked data are operated on by different functions (Unix commands). (Also the duality is kind of similar to MapReduce idea, to pass around functions on data in the distributed system rather than data itself, which probably explains why MapReduce is so amenable to FP rather than OOP.)

It also seems to me that utilizing this "inversion of control" one could convert any OOP pattern into FP pattern - just instead of passing objects, pass the function (method which takes the object as an argument) in the opposite direction.

I am not 100% convinced that FP approach is superior to OOP, but there are two reasons why it could be:

1\. The "nakedness" of the data in FP approach makes composition much easier. In OOP, data are deliberately hidden from plain sight, which destroys some opportunities.

2\. In OOP, what often happens is that you have methods that do nothing rather than pass the data around (encapsulate them differently). In FP approach, this would become very easy to spot, because the function that is passed in the other direction would be identity. So in FP, it's trivial to cut through those layers.

<comment><USER51> [http://people.csail.mit.edu/gregs/ll1-discuss-archive- html/m...](http://people.csail.mit.edu/gregs/ll1-discuss-archive- html/msg03277.html)

</comment></comment><comment><USER52> 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.

<comment><USER53>
        data Case = CaseSensitive | CaseInsensative

This is just as efficient as the newtype, and leads to clearer code when matching on the value.

Also, sometimes types you thought only had two inhabitants get a third one added later, which this facilitates.

<comment><USER52> Clarity is a bit subjective, I think. The difference between:

        CaseSensitive
        CaseInsensitive

Is harder to spot (for me) than between:

        CaseSensitive True
        CaseSensitive False

This is because the bit that is the same is all on one side, and the bit that is difference is all on the other side. Case in point, your data definition has a typo: `CaseInsensative`, which occurs after the `In` shifts it away from the bit it should be the same as in `CaseSensitive`. Every little bit helps.

What's more, while you may be right that at the surface, the two representations are equally performant, what the newtype has that the data declaration does not, is the Prelude's definitions of all the boolean operators. If you wish to perform any more complicated logic with your data declarations treating them as booleans, you must either cast them to booleans (which comes at a runtime cost), or you must replicate the functionality of the Prelude for your custom type (which comes at a development cost).

Your branching logic (which, let us suspend disbelief and say is "not so bad", just for now) may require the combination of multiple such booleans, which in your encoding scheme would each get a different type due to their semantics, then we can't even viably define our custom boolean operators, so are forced to cast everything to booleans.

The point I'm making here is that outwardly, you want the type to reflect the semantics of how its values are used, but inwardly, you want access to its representation in a way that makes it easy to combine (or put another way, depending on who's looking, the semantics of a value changes).

Also, there is nothing stopping you from changing code later to meet changing needs. Using a newtype now doesn't preclude you from ever using a data declaration in the future. Certainly, you will have to change the patterns and constructors used in a couple of places, but that is a matter of minutes: Time you have already spent weighing the future implications of this decision in your mind right now, so this sensation of time saved is a fallacy.

</comment></comment></comment><comment><USER54> I thought the argument was going to be "Conditionals are bad for running on GPUs."

</comment><comment><USER55>
        It's no wonder that conditionals (and with them, booleans) are so widely despised!

They are?

<comment><USER56> 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 say, I really don't understand what he's getting at. The last example he gave seemed to make things even more complicated, and it basically renamed "true" and "false" to more descriptive things (forRealOptions, dryRunOptions), which seems to my untrained eye to boil down to the moral equivalent of a C enum.

[0] [https://en.wikipedia.org/wiki/Material_conditional](https://en.wikipedia.org/wiki/Material_conditional)

[1] [https://en.wikipedia.org/wiki/Quicksort#Algorithm](https://en.wikipedia.org/wiki/Quicksort#Algorithm)

<comment><USER57> > 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.

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

</comment></comment></comment></comment><comment><USER59> view-source:[http://antiifcampaign.com/](http://antiifcampaign.com/)

Find in page: 'if('

2 hits.

So, yeah.

</comment><comment><USER60> This is the starter code:

        publish :: Bool -> IO ()
        publish isDryRun =
          if isDryRun
            then do
              _ <- unsafePreparePackage dryRunOptions
              putStrLn "Dry run completed, no errors."
            else do
              pkg <- unsafePreparePackage defaultPublishOptions
              putStrLn (A.encode pkg)

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 defaultPublishOptions
              IO.puts (A.encode pkg)
        end

Pattern matching is pretty powerful, even going as far to give a dynamic, non- statically types language like Elixir the ability to 'destroy all iffs' too.

<comment><USER61> 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 inputs and check for nulls in some languages, which can help you avoid null pointer exceptions and such. But you haven't encapsulated anything, or saved yourself any thinking or typing, by using pattern matching. You've basically turned every function into a switch statement. It's vastly overrated.

<comment><USER62> Another advantage of pattern matching is extensibility.

Suppose you wish to add a new branch case. Under the traditional if/else (or switch) model, you'd need to modify the function containing the if statements. With pattern matching, you simply introduce a new function; it decentralizes the change and acts as a sort of simple, intuitive polymorphism.

</comment></comment></comment><comment><USER63> Reducing if statements does shrink the possible state space, however using additional abstraction might increase it even further.

</comment><comment><USER64> 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.

</comment><comment><USER65> 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?

<comment><USER40> I'd love more data on this too, but I do think it's worth pointing out that it's pretty uncontroversial that the more control flow paths you have, the harder your code is to reason about. That's the basic assumption of the notion of cyclomatic complexity, after all.

</comment></comment><comment><USER66> I think pattern matching is fine, I don't see how it is still "boolean". The additional techniques shown are interesting, but heavy abstractions that should not be prescribed in general.

</comment><comment><USER67> This was the idea I used when I did

[https://bitbucket.org/iopq/fizzbuzz-in- rust/overview](https://bitbucket.org/iopq/fizzbuzz-in-rust/overview)

I still had to bottom out at [https://bitbucket.org/iopq/fizzbuzz-in- rust/src/9e5fcaabbd5f...](https://bitbucket.org/iopq/fizzbuzz-in- rust/src/9e5fcaabbd5f364839be929a974db0ac31d79c2e/src/lib.rs?at=master&fileviewer=file- view-default#lib.rs-53:56)

</comment><comment><USER68> Paul Blasucci had a good talk on Active Patterns (an F# language feature):

[https://github.com/pblasucci/DeepDive_ActivePatterns](https://github.com/pblasucci/DeepDive_ActivePatterns)

This feature allows to encapsulate conditional matching on arbitrary input and dispatching.

For those who know ML, it is making the concept of pattern matching extensible to any construct.

</comment><comment><USER69> Since this is about FP, we have to have recursion:

[https://www.reddit.com/r/functionalprogramming/comments/4t91...](https://www.reddit.com/r/functionalprogramming/comments/4t913u/destroy_all_ifs_a_perspective_from_functional/)

</comment><comment><USER70> This is the best bit I think:

> The problem is fundamentally a protocol problem: booleans (and other types) > are often used to encode program semantics.

> Therefore, in a sense, a boolean is a serialization protocol for > communicating intention from the caller site to the callee site.

</comment><comment><USER71> Less if is better, I agree on that. Lamdas technique is interesting because they "encapsulete" a specific case. In OOP this is achieved by using polymorphism on the objects instantiated for the right case. Right?

</comment><comment><USER72> If 'if' could support single 'expression' and multiple 'case's like 'switch/match', it would make easier the transition.

</comment><comment><USER73> only a sith speaks in absolutes

</comment><comment><USER74> sounds like what's really being said is..

It is recommended that programmers use abstractions whenever suitable in order to avoid duplication, and associated errors

</comment><comment><USER75> i can't think of use of 'if' in a math function; however, if is implicitly used in input, say 0<x<1, f(x)=x, 1<x<3, f(x)=x^2

i see a lot of loop though, summation is so a double integral is loop within loop. i can't think a code analogue with derivative

fta, i take that if in function body makes an ugly code.

<comment><USER76> Lots of math functions are defined with 'if' \-- the absolute value, the Heaviside step function, etc.

</comment></comment><comment><USER77> Sandi Metz talks about ifs a bit here: [https://www.youtube.com/watch?v=OMPfEXIlTVE](https://www.youtube.com/watch?v=OMPfEXIlTVE)

</comment><comment><USER78> You can go a long way without Ifs in a pattern-matching language like Prolog or Erlang, too.

</comment><comment><USER79> Ummm. Many common day to day languages don't use lambdas. Also I have no idea what they are. So - yeah I don't think you can just replace if so easily.

<comment><USER80> Lambas are actually supported in most popular languages: C++, Java, C#, Go, JavaScript, even C. Sometimes they're called function literals or anonymous functions, but basically they involve creating a function without a name that can be passed around and executed. In some languages (Haskell, OCaml, etc) the anonymous functions can be extremely generic, whereas they are sometimes a bit less flexible in other languages. If you want a quick intro you can find one here: [http://stackoverflow.com/questions/16501/what-is-a-lambda- fu...](http://stackoverflow.com/questions/16501/what-is-a-lambda-function)</comment></comment>