• doubting_poster (unregistered)

    what does it even do?

  • Adam “OOPMan” Jorgensen (google)

    Huh, pipeline operator. Huh.

    You know...

    I've been working on a library that implements that kind of thing in Python

    You can look at it here: https://github.com/OOPMan/rightshift

    Please don't use it though. I have come to conclude it's an abomination and mainly just toy with it now and then to see what new levels of meta-programming abuse can be achieved in Python. If case you're wondering, the answer is: plenty :-)

  • Prash (unregistered)

    My team write F# just fine with lots of pipes (almost every function has some). I think they're easier to follow if language features support it (e.g. static types, currying). And they reduce having to find names for things that would be difficult or impossible to name meaningfully.

  • fsi (unregistered) in reply to doubting_poster

    Jesus Christ on a stick, I might've spent too long decyphering this, but from what I've gathered:

    It's a curried function that takes an Array of "breakdowns" (e.g. ["foo", "bar"]) and then, an equal-length Array of Arrays of... things. These last Arrays may be nested, R.map(R.flatten) will take care of that.

    Then it "zips" the "breakdowns" array with the "things" array like so: [ [ "foo", things1 ], [ "bar", things2 ] ]

    Then, via near-uncomprehensible Ramda magic, it groups the "things" by the value of the field given by "breakdown".

    So, if I had an array of... things... and I wanted to group it by id and, say, color, I'd go

    groupByBreakdown(['id', 'color'])([things, things])

    Of course, this function is way more flexible as these two arrays might be different arrays, so in one fell swoop I could group puppies by weight and flowers by color and npcs by level:

    groupByBreakdown(['weight', 'color', 'level'])([puppies, flowers, npcs])

    It's KIND OF useful, but cumbersome, tries to do too many things at once and is completely backwards.

  • (nodebb)

    It might be because of how little work I do with actual algorithms compared with how often I play "find the fucking code", but this isn't that much of a WTF to me.

    Sure I'll reread it a few times and take it apart to see how it works, it's a single function which does ONE thing: turns data into other data. Sure, it's a bit weird about it, but if I'm looking at a function and saying "what's going on here?", it's because I've gotten past my repeating nightmare of finding the function I need even though it's been put in an unintuitive location.

    Javascript isn't actually that great for functional programming but people are trying to make it so that it is (started with jQuery and now we have things like Immutable and Maps and NodeJS's require, even though that's being scrapped for ES6 import, I guess) but it won't fix the main issue with Javascript: developers think they can dump the code anywhere and "everything will be fine", because they wrapped it in a name like "fnc1" or something. No thought gets put into scalability, intuition or separation of concerns so noobs (including people who don't take javascript seriously but choose to develop in it anyway) just put the code any-old-where and it won't be their problem to fix (somehow it's always been my problem to fix).

    Basically, I've seen Angular services in monolithic Hybris applications called "service". I agree this incessant piping is difficult to read, but that's what comments are for. This doesn't scare me.

  • No Fun (unregistered)

    Erm, hate to break it to you, but if you're remotely used to functional programming this... isn't WTFy. It isn't that weird. It reads quite clearly, it's compact, maintainable. Granted, if you're a JS grunt who doesn't get functional programming you won't understand this, but saying "This is a WTF because it's functional and I don't know how that works" is... not a great attitude.

  • RLB (unregistered) in reply to No Fun

    Sure, in Prolog or Icon it wouldn't be a WTF. Trying to built it into JScr... JavaSc... EczemaScript, that is a WTF. And using R.pipe with R.apply((())), well, at least it smells of a WTF.

    Basically, pipelines are great... if you make sure that everything sticks to pipelines. Having, or enabling, pipelines within nested function calls within pipelines, that's not a good idea.

  • bills (unregistered)

    http://bit.ly/2HE2bnk

    god help me what have I done?

  • What (unregistered)

    That's not even Reaasonable

  • MarkV (unregistered)

    So for those of us who aren't functional programming gurus, what does this do? Why is this a WTF? What would be a better way to do whatever it does?

  • LzzrdBorth (unregistered)

    Some days, especially Mondays, I'm a barely functional programmer.

  • 🤷 (unregistered)

    From yesterday's article: "so instead they opted to use the tools they aalready understood" From today's article: "Shells support pipelining for a reaason"

    I see a paatern there.

  • James (unregistered) in reply to Prash

    No name is better than a bad name, but if you can't find a meaningful name, why not just use a single letter?

  • I dunno LOL ¯\(°_o)/¯ (unregistered)

    This code appears to be slightly more readable than obfuscated Perl. At least you can make out bits that look like common English words.

    In the immortal words of Beavis and Butthead, "heheheheheh He said 'pipe'".

  • Smash (unregistered) in reply to 🤷

    What are you taalking about?

  • Aegeus (unregistered)

    The pipeline isn't responsible for the WTF - it's the only part of this code that's actually easy to read. It's the things they're doing inside it that are WTFs.

    R.map(R.flatten), for instance - that means that they have an array, which contains more arrays, which themselves contain more arrays. And they want to flatten out only the inner arrays, leaving you with just an array-of-arrays. So our data is looking alarmingly complicated even before we start processing it.

    The other WTF is the last line, R.map(R.apply(R.useWith(R.groupBy, [R.prop, R.identity]))) - that's a very large number of functions that do nothing but tell you how to apply other functions. The thing that it's actually doing is the last bit - R.groupBy, [R.prop, R.identity] - but good luck figuring out exactly how it's being applied.

    Oh, and this whole method returns a function, not a value. So we're looking at a factory pattern on top of all this. This code was a WTF well before the piping happened.

  • HK-47 (unregistered)

    If you look at the example given in favor of pipeline operator you cannot but wonder why not just write ((n * 4) + 1) * 2? I know it is a contrived example, but if even your contrived example can be so easily simplified and written in so much more readable way, then perhaps your solution is entirely unnecessary?

    Either that or you suck in giving proper example of the usability of such feature and you should not be allowed to contaminate any programming language until you can prove that what you are suggesting could actually be useful.

  • Sole Purpose of Visit (unregistered) in reply to fsi

    I'm with you and the Functional Programming guys. (Granted, I'm not a FP guy, but still.)

    Both the submitter and Remy appear to be having their cake and eating it. "Oh look, it's functional programming! Functional programming is good, except when it isn't!" And there the WTF comes shuddering to a halt ... because this FP snippet probably (I say probably, because there is a lack of context, and anyway I don't do FP naturally) does what it's supposed to do.

    Basically, it runs a map of "something" through a series of partially applied functions, and returns a function -- this last being obvious because the type declaration tells you that. I've got no experience with pipes in JS (and on a side-note, I disagree vehemently with the claim that pipes in bash are a thing of unambiguous wonder), but they seem to be a red herring here: they're just the way you have to do this in JS. I assume. Call it boilerplate, or infrastructure.

    It's interesting that it seems to flatten a map, then zip it (back into a list of tuples, assuming that JS zip works the way you'd expect), then apply another function to use the mapper "GroupBy" in order to produce .... er, well, I'm not sure, but an ordered list of lists of tuples, or something. I'm sure there's a better way to do this. But on the other hand, as the consumer of this function -- you don't really care. It's a bit obfuscated, sure, but the obfuscation is purely internal. The only question worth asking is, does the resultant function do the job?

    I'd like to see a reworking of this in Haskell, or possibly OCamL or F#. I suspect a language that is better suited to expressing ML would make it abundantly clear what the intention and the result is. (Haskell, for example, wouldn't just return Function: it would return a fully-typed definition of the function. Which would be a sight more helpful than a catch-all type that basically means "an object that is a function with an arbitrary list of parameters of arbitrary types that yields an arbitrary type ..."

  • scooby (unregistered) in reply to Adam “OOPMan” Jorgensen

    Well, it's a worthwhile experiment.

    This module https://github.com/scooby/pyrsistent-mutable lets you write code using immutable data structures, but as entirely ordinary imperative Python. It's much nicer when you have complex nested structures and classes.

    Should be making a PR to roll it into pyrsistent when I get around to it.

  • Cat (unregistered) in reply to Sole Purpose of Visit

    @Sole Purpose of Visit - The declaration doesn't tell you it returns a function. JavaScript doesn't do variable or return typing. The keyword function simply defines groupByBreakdown as a function.

  • Tab (unregistered)

    TRTF is 8-space indentation

  • Abe Z. (unregistered)

    Yeah, and debugging is really very easy with pipes, esp. when combined with partial arg. application and function composition. Ideally when you need to fix a piece of code you haven't seen before.

  • doubting_poster (unregistered) in reply to fsi

    thanks for the effort! And for the guy making the sweeping generalisation "Erm, hate to break it to you, but if you're remotely used to functional programming this... isn't WTFy." - I have more than a remote knowledge of functional programming, but I couldn't see what the goal of this function was.

  • Adam Jorgensen (github) in reply to scooby

    Nice!

  • read (unregistered)

    http://bit.ly/2phN2jP

  • Jimmy Bosse (unregistered)

    The only problem with that code is naming. this is a poor straw-man for a bad argument. If you think Javascript is a bad language, then a functional style is the style that will cause you the least suffering in javascript.

  • eric bloedow (unregistered)

    the name of this story reminded me of an older story where a "programmer" who disliked the "pipe" (|) symbol told the system to replace every "|" symbol in EVERY program with something else...with disastrous results!

  • Paul Neumann (unregistered)

    F# translation (I think):

    let groupByBreakdown (breakdowns: seq<'breakdowns>) (args: seq<seq<'args>>) =
        Seq.map Seq.concat args
        |> Seq.zip breakdowns
        |> Seq.map (fun (b, x) ->
            let prop = x.GetType().GetProperty(b).GetValue
            Seq.groupBy prop x
        )
    
  • HK-47 (unregistered)

    Just wait until they invent pipe operator overloading...

  • Wheresthespamohthereitis (unregistered)

    Quit spamming, "Steve"

  • MaxArt (unregistered)

    the proposed pipeline operator is a terrible idea whose time isn’t going to come. Ever.

    The pipeline operator has recently reached stage 1 as a TC39 proposal. It could still be pulled, though, but if you want to fiddle around it Firefox already supports it behind a flag.

    Anyway, I don't see that much of a WTF here. Sure, they could have broken the operations into more semantically named sub-operations, but it looks pretty decent to me. FP implies a change of mind, and that makes you think it's all WTF.

  • OlegYch (unregistered)

    i get that you don't understand fp, but what's wrong with the snippet in your opinion, Remy?

Leave a comment on “Flushed Down the Pipe”

Log In or post as a guest

Replying to comment #494344:

« Return to Article