34

I hang out in the tag a lot and there are frequently questions from people learning functional programming for the first time.

It is usually pretty obvious who they are, but I like helping people learn my favorite language. Frequently someone will ask how to do something in the way one would solve the problem in an imperative language. Technically, it can be done using advanced language features, but it is probably better to approach the entire problem in a different way.

In these cases, is it better to answer the question asked, or to suggest how to solve the problem better given in a functional language? (or perhaps both?)

8
  • 1
    I try not to provide answers that do things i wouldn't suggest, even if it solves the problem.
    – Kevin B
    Commented Aug 10, 2018 at 22:16
  • 4
    Since answers are meant to be useful to others too, not just the OP, I'd lean toward the latter because it sounds like most programmers are going to want to do it the functional way. If the OP indicates that they can't do it that way for some reason you might add the other solution with caveats/warnings.
    – BSMP
    Commented Aug 10, 2018 at 22:37
  • 3
    My favorite answer on any Stack Exchange site: How to disable kill command on linux. Don't do it is the right answer, but this answer tells you how, with the disclaimer "Devastating side effects are expected."
    – Davy M
    Commented Aug 10, 2018 at 22:53
  • 2
    It's probably safe to assume that they want to know the functional way to do it, otherwise why bother learning Haskell in the first place. But I guess you could post a quick comment asking "Are you sure you want to do it that way, or do you want to learn the functional way?"
    – PM 2Ring
    Commented Aug 10, 2018 at 23:06
  • I'd say both, as everyone reading the answer can decide for the most fitting approach, heres how I answer in such cases: stackoverflow.com/questions/50245957/… Commented Aug 11, 2018 at 15:28
  • 1
    Re "but I like helping people learn my favorite language": But you do cast close votes for duplicates, right? Commented Aug 12, 2018 at 7:26
  • 1
    In the world of SQL there are frequent questions regarding doing questionable things. In many cases they are problems where an ad-hoc fix is needed. Posting an answer that includes an explanation of why the answer is not generally applicable is common, e.g. a one-time import of "dirty" data that needs to be cleaned up might have terrible performance but suffices for the OP's problem. SQL injection is another common issue. A solution used in a trusted environment for a limited purpose might not be something you would want in production.
    – HABO
    Commented Aug 12, 2018 at 14:08
  • Useful reference: Pounding A Nail: Old Shoe or Glass Bottle? Commented Aug 12, 2018 at 19:22

5 Answers 5

16

Sometimes, showing them how to do it is the best way to show them not to do it.

-- 10 lines of ugly code
-- that uses all those advanced features

To understand what it's doing… well, first, this will only make sense if you understand how the IO monad works under the covers. See here if you don't (see here if you don't even know what the IO monad is besides some handwavy magic).

The trick is that XXX, which… here's another paragraph.

Once you get all of that that… well, it's still not easy to understand, but it's at least possible. And now you can see why it's so ugly—because what we're doing is inherently ugly in a pure language like Haskell.


Meanwhile, if you did this:

-- 2 lines of easy code

… it would accomplish what you're actually trying to do. To understand why, here's a short novice-friendly paragraph.

Rarely, this won't work. If you need to Foo a Bar, you have to Qux the Spam like I showed above. But that doesn't seem to apply to your case—as it doesn't in most cases—so there's no need here.

As jpp points out in a comment, doing it the other way round—show them how simply the idiomatic solution gives them the answer they want, then show why the way they wanted to do it is a pain—should be just as useful to the OP, while being more useful to a wider class of future readers. (And it doesn't seem like it could hurt anyone. For a future reader who really is in the rare situation of needing to do what the antipattern does, there's oo harm in seeing the idiomatic solution, and thus confirming why it isn't what they want here, before seeing the clunky but necessary solution.)

2
  • 8
    I like this, but how about reversing the order of the answer. Here's the conventional way.... Now here's what's wrong with your original method...... The reason I suggest this is there are many ways you can make an answer anti-pattern, but there are fewer recommended solutions to a problem. Catering for the wider audience, a good answer should focus, in my opinion, on the "correct and good" way.
    – jpp
    Commented Aug 12, 2018 at 16:55
  • 2
    @jpp Yeah, that's a good point. Looking over my answer history, I've done it both ways, and your order seems to generally read better on reflection.
    – abarnert
    Commented Aug 12, 2018 at 19:01
12

First and foremost I consider what a reasonable person who finds the question might find helpful.

This sounds subjective, because it is. The fact is XY problems are very common in new askers. Correcting errors in anti-pattern1 logic never deserves a downvote. After all, you are fixing OP's immediate problem. But, in my experience, a good answer will provide an appropriate solution to the underlying problem, even if it's not in line with OP's original thinking.

Here's a classic example: How do I create a variable number of variables?

The top-voted answer with +187 doesn't actually answer the question as stated. But provides a solution which many people have found useful. More useful than answers (2) and (3) combined, ordered by votes, which attempt to address the question directly.

Here's another example from a question I answered today where I deliberately bypassed the "give me a one-line answer" criterion placed by the OP. Because I feel future visitors would benefit from an alternative solution. There are countless other examples across SO.

1 By anti-pattern, I mean any of: inefficient, unclear, unmaintainable, posing security risks, against the precepts of a particular framework.

3

We do need to directly answer questions otherwise there'd be way too much ambiguity introduced to many answers. E.g.
"I know you are using PHP, but this is so much easier in Python..[answer is a Python based approach]"

Given this, you should answer the question directly within the proposed scenario, answer in a way that utilises the askers preferred approach/etc to give them the "answer", then expand to explain a possible better approach. This way you've both answered the question and fulfilled their exact requirement, but you've also added some decent advice for a better approach.

It's like answering a question about a bug in a mysql_ query by providing a PDO answer. Sure they really should make the change, but even large corporates still have some old legacy floating around with mysql_ here and there. The question is about mysql_ and answering it with PDO is not answering the question, that's just advice about how they can improve their approach.

Technically, it can be done using advanced language features, but it is probably better to approach the entire problem in a different way.

Consider this example:

Q: I don't have a screwdriver but need to put a screw into a wooden wall to hang a picture. I have a hammer.
A: Simple, use that hammer and whack it into the wall.

Is it a good idea to do this? Not really.
Is it good advice? Not really.
Does it work? Possibly - this depends on what you define as "it works" and what level of quality you want.

There are many reasons to not hammer a screw into wood. It's bad advice, whether it works or not, and you should really strive to give good advice. So here you'd explain basic ideas on how to go about this the "hacky" approach they requested, and then list the potential pitfalls (damaged head, bent screw, damaged wood, etc). And then go on to explain they should really use a screwdriver.

"It works" - the screw is hammered in, the picture is hung up. Job done right? Wait until it falls out, or you need to take it out and you ruined the head so can't simply unscrew it and have to use pliers or a claw hammer (etc).

This is the same with bad code or a poor design approach to the problem. It might fix that precise single issue, but it introduces more problems elsewhere or in the future.

9
  • 2
    Your examples don't really apply to the Haskell situation, though. Many familiar tasks in imperative languages get approached quite differently in functional languages. Trying to replicate the imperative techniques in Haskell can easily lead to inefficient ugly code using advanced language features that beginners should not be bothering with. They need to learn the functional idioms instead, but they don't yet know the language or paradigm well enough to ask their question in a functional way, so they fall back on the familiar imperative patterns.
    – PM 2Ring
    Commented Aug 10, 2018 at 23:13
  • @PM2Ring I'll take your word for it, but are you sure this doesn't work for Haskell? Does it not work for anything where the wrong tool (or design approach) is used to do a task in a poor way. Not even the basic premise of "answer the question directly, then add advice after"?
    – James
    Commented Aug 10, 2018 at 23:19
  • 1
    Almost all Haskell coders learn at least one other language before they try learning a functional language. Those languages give you a different set of tools and a different way to approach programming tasks. These tools and the ways to use them don't easily map to the imperative skills that a new Haskell coder (probably) has. When trying to solve a coding problem, it's natural to fall back on what you know when you're unaware of the Haskell way, but that's often likely to lead to XY problem territory.
    – PM 2Ring
    Commented Aug 11, 2018 at 0:38
  • Similarly, when you're trying to explain your problem, you're likely to use imperative language, purely because that's what you're familiar with, and you haven't yet picked up the functional jargon.
    – PM 2Ring
    Commented Aug 11, 2018 at 0:38
  • I somewhat agree with your point, but the examples you use feel off the mark. "It's easier in Python" is opinion based, while answering mysql_* questions is simply dangerous, for other internet users, OP, and everyone involved with any site that person will make. I'm all for supporting old technologies, but some things are just reckless. Commented Aug 11, 2018 at 0:44
  • 1
    @FélixGagnon-Grenier "answering mysql_ is dangerous" it doesn't matter IMO. The OP is using mysql_ in their code and so they need help with mysql_. If you just want to answer with PDO then you have to wait until they're using it and asking about it. Maybe the business doesn't have the budget to change all the mysql_ stuff yet? There are unavoidable reasons it's still used a lot.
    – James
    Commented Aug 11, 2018 at 0:49
  • Yes, you are right @James, there are unavoidable reasons. I'm mostly arguing about it because I feel powerless about that. People will continue to use it, even though it's been deprecated years ago. I disagree that we should just continue to answer these; I think we should still always offer a sql agnostic answer, as well as point to PDO. Commented Aug 11, 2018 at 0:57
  • 2
    @FélixGagnon-Grenier I agree, as per my answer ;) "Given this, you should answer the question directly within the proposed scenario, answer in a way that utilises the askers preferred approach/etc to give them the "answer", then expand to explain a possible better approach."
    – James
    Commented Aug 11, 2018 at 1:07
  • 2
    Gods, I should really learn to read. Commented Aug 11, 2018 at 1:15
3

This is something I think we have to be careful with.

On the one hand, yes, many askers are misguided or confused. Declining to answer their original question, explaining why that question is misguided, explaining what they should be asking instead, and then answering that other question, is often the proper approach.

But on the other hand, telling someone they're asking the wrong question, and refusing to answer the question as asked, can be (and sometimes is) really, really rude. I've lost count of the number of times that:

  1. I've seen askers figuratively pound the table in frustration, insisting that they do really want to do X, begging people to just give them some help doing X, already.

  2. I myself have asked a question about doing something that I know full well is classically a bad idea (or even impossible), explaining that I know this, explaining that I really do have a bizarre need to do the wrong/impossible thing, only to have six regulars skim my question for 1.5 seconds before leaping to the conclusion that I am Yet Another newbie asking that classically misguided question, and launching into patronizing lectures to that effect.

So this is a great example of an area in which, despite our best intentions, we can seem rude and unwelcoming. I would encourage people to be careful with this. Any time you find you're about to do something which is the moral equivalent of saying:

Your question is misguided. You should not want to do X in this situation. You should want to do Y instead. Here is how to do Y.

please stop and think. What if the OP really, truly does want to do X? What if they really, truly have no interest in doing Y? Perhaps, if you have no interest in helping them do X, you should save time and effort by not answering their question at all.

Now, yes, I know. In situation 1 that I described above, if X really is a truly bad idea, it's not important to spare the OP's feelings, sometimes you have to be blunt and tell them the hard truth. But on the other hand, there are lots of beginners who are just not ready to do Y. You, the expert, know with absolute certainty that X is wrong and Y is right, but the beginner's mind is simply not prepared to accept this reality just yet. Sometimes, the road to enlightenment really does involve a detour through X, trying it and watching it fail and learning that it doesn't work. Only then can one accept that Y might be worthy of consideration.

And then there's situation 2. Again, there are plenty of regulars who have an absolutely unassailable faith that X is either wrong or impossible, that no one should ever want to do X. But let's think abut two analogies.

(1) Suppose that, through no fault of my own, I find myself by the side of an isolated mountain road, in the dark, in the rain, with a flat tire on the car. Suppose it's not my car, and I discover that although there's a spare tire, for some reason the jack is missing. And suppose I'm asking for suggestions of what to do in this situation. Do you want to be the person who says

You should not try to change a tire by the side of a mountain road in the rain without a jack. You should always change tires in a clean, well-lit garage, with a smooth floor and proper jacking equipment. Not only is it easier, it's much safer that way.

(2) Suppose it's 1902, and Orville or Wilbur Wright pop up on mechanics.stackexchange.com to ask if anyone has ideas for a lighter but more powerful engine for the aeroplane they're trying to build. Do you want to be the person who says

Heavier-than-air flight is impossible. Why are you trying to fly, anyway? This is an XY problem. You're trying to fly, but what you really want to do is get from point A to point B efficiently. If walking isn't efficient enough, why don't you try riding a bicycle?

5
  • 1
    In general, a good answer. The only issue I have is in being careful with edge scenarios [let's face it, there are many more "anti-pattern" questions from inexperienced programmers], you may encourage "correct but bad" logic. I think the onus should be on the questioner to explain why they want to do something the "inadvisable" way. Then you have to trust people read the entire question. Hard to do, but necessary for a good Q&A.
    – jpp
    Commented Aug 12, 2018 at 16:04
  • I agree with @jpp here. And sometimes it's worth a few comments to clarify. To make this concrete, consider the common Python question "I'm iterating a list and calling remove on the ones that match, but it skips some of the matches." Sometimes they can't just build up a new list, can't just xs[:] = [the new list], and can't just iterate reversed(enumerate(xs)), so they need the while i < len(xs) answer—but their question should (be edited to) make it clear why the more common answers are all inappropriate. Then future readers can tell whether they have the same (rare) question.
    – abarnert
    Commented Aug 12, 2018 at 19:24
  • So, instead of saying "Heavier-than-air flight is impossible, just try riding a bicycle" say, "I'm assuming there's a good reason you can't just ride a bicycle. Maybe you need to go over a wall, or maybe you're doing this specifically to learn how flight works (or doesn't), or maybe you need an engine that would be powerful enough to fly a plane even though that's not actually what you're using it for, or maybe something I haven't even thought of. If you can edit to explain which one it is, we can probably give a better answer."
    – abarnert
    Commented Aug 12, 2018 at 19:26
  • (1) Analogy 1 is bad. You should not use Stack Exchange in emergency situations, and you should explain your context/rationale for doing that (I'm stuck in <...>, I can't use a <...>) (2) Whoever "insist and beg" may be considered "not nice". (3) I can't tell for sure what exactly is "situation 2" above without specific example.
    – user202729
    Commented Aug 13, 2018 at 14:35
  • @user202729 "You should not use Stack Exchange in emergency situations." Not saying I disagree, but is that stated anywhere? Commented Aug 13, 2018 at 22:26
0

I am mainly working the java tag, and it is pretty simple: there are enough people around who will give the technically correct answer, and instruct the questioner how to shot himself into the foot, very often not even mentioning the problem with the suggested answer, or how to otherwise approach the problem.

Therefore I have no quarrel adding another answer and telling people: "you are going down the wrong rabbit hole" or something alike, to then explain what the problem with their approach/question is, and to outline the "better" solution. You wouldn't believe how many people simply don't understand how to write easy-to-unit-test Java code. And then people suggest to go for "advanced" mocking frameworks, instead of simply making the production code easier to test.

Keep in mind: we don't write answers just for the OP. Anybody coming by with a similar problem deserves the best solution. And "flip your shot gun open, insert two shells, close it, aim for your right leg, pull the trigger" isn't a helpful answer, albeit technically correct.

Not the answer you're looking for? Browse other questions tagged .