Clojure WTF



  • Someone went Lisp is awesome blah blah , functional programming is cool , enlightenment in store blah blah bulshit and after a lot of blahs and awe-inspiring Lisp stories, I gave Clojure a try.

    I started with http://www.braveclojure.com. Everything was smooth so far, learnt about the basics, functions, data structures and all that, and now I find myself looking at

    (defn matching-part
      [part]
      {:name (clojure.string/replace (:name part) #"^left-" "right-")
       :size (:size part)})
    
        (defn symmetrize-body-parts
          "Expects a seq of maps that have a :name and :size"
          [asym-body-parts]
          (loop [remaining-asym-parts asym-body-parts
                 final-body-parts []]
            (if (empty? remaining-asym-parts)
              final-body-parts
              (let [[part & remaining] remaining-asym-parts]
                (recur remaining
                       (into final-body-parts
                             (set [part (matching-part part)])))))))
    

    Basically this is an example where the words containing "right" in a list( vector in clojure ) is duplicated with the word "right" being replaced by "left"

    Looking at this shit makes me wanna kill myself.

    1. Is this because I am not used to so many fucking parantheses ? I find it mentally hard to match each them in my head.

    2. Is this code too contrived or non-trivial Clojure code usually looks like this ?

    3. Is there actually an enlightenment experience at the end of it all If i manage to torture myself through this ?

    4. Do languages like Haskell, F#, Scala or one of those new hipster languages employ the same mindfuckery/torture to implement stuff like this ?

    5. Am I TRWTF for even having gotten myself here ?



  • Also >lein repl is slowwwwwwwwwwwww as fuck on startup holy shit man.


  • Garbage Person

    I put Lisps into the Esoteric Language bucket. Academic eggheads and silly valley brogrammers might have time for that shit, but working developers don't.


  • area_pol

    I am not an expert in functional programming, but I had Haskell, OCaml, Scala at university, and for me this code is completely incomprehensible.

    @stillwater said:

    Do languages like Haskell, F#, Scala or one of those new hipster languages employ the same mindfuckery/torture to implement stuff like this ?

    Scala, as "functionally" as I was able:

    val left_parts = List("left hand", "left leg", "qua")
    
    // Make a regex object which finds string like "left <something>"
    val pattern = "^left(.*)$".r
    // If a matches "left <something>", add "right <something>" to the list
    val all_parts = left_parts ++ left_parts.collect {
        case pattern(what_remains) => "right" + what_remains
    }
    
    println(all_parts.mkString(", "))
    

    But Scala is not a "pure functional" language, you can switch between functional and Java-like when you want. The nice thing is that you can use all the JVM ecosystem, while esoteric languages suffer from lack of libraries.



  • This scala code looks million times saner than the clojure slippet I provided.

    @Adynathos said:

    and for me this code is completely incomprehensible

    Phew! Thank Fuck I am not the only one.



  • @Adynathos said:

    Haskell, OCaml

    Is there a way you can objectively tell if one is better than the other?



  • Beneath the shiny surface and bright promises of pure functional languages, there is always the horrifying messy reality of actually trying to use them in a real world situation. As you've just discovered.



  • How does loop work?


  • BINNED

    @stillwater said:

    s this because I am not used to so many fucking parantheses ? I find it mentally hard to match each them in my head.

    Matching parentheses in your head is :doing_it_wrong:. The editor should be able to do it for you. If it can't, find another editor.



  • Umm I am on the phone and it is hard to explain here but trust me you don't want to know. It is a bit fucked up.Those things inside the square brackets are some kind of loop indexes thingy.

    I WANT TO UNSEE ALL OF THIS SHIT.



  • @stillwater said:

    Is this because I am not used to so many fucking parantheses ? I find it mentally hard to match each them in my head.

    That might be it. I've been doing Clojure on and off for a couple of years. The parens don't bother me.

    @stillwater said:

    Is this code too contrived or non-trivial Clojure code usually looks like this ?

    Looks like it could be re-written with mapcat... I started a repl, dumped in the your code and came up with this:

    (defn symmetrize-body-parts [parts]
      (vec
        (mapcat
          (fn [p]
            (let [mp (matching-part p)]
              (if (= p mp) [p] [p mp])))
          parts)))
    

    Is that any better?

    Maybe it would be familiar like this:

    (defn symmetrize-body-parts [parts]
      (vec
        (mapcat
          (fn [p]
            (let [mp (matching-part p)]
              (if (= p mp)
                (vector p)
                (vector p mp)
              )
            )
          )
          parts
        )
      )
    )
    

    Yet another version:

    (defn symmetrize-body-parts [parts] (vec (mapcat #(set [% (matching-part %)]) parts)))
    

    My recent experience, from the last few minutes, tells me that you'd really have to like playing with code and challenging yourself to get over the hump of learning a language with very different idioms and syntax. You're kind of starting over in that you won't know how to do even basic things that are effortless to you in your favorite language.

    There's a reason why 99.99% of languages look like C.

    @stillwater said:

    Is there actually an enlightenment experience at the end of it all If i manage to torture myself through this ?

    The claims of enlightenment are greatly exaggerated. But there are many great ideas in these "out-there" languages that you can employ in more conventional work.



  • @antiquarian said:

    Matching parentheses in your head is :doing_it_wrong:. The editor should be able to do it for you. If it can't, find another editor.

    Most editors do that. Sublime does it. I meant something else. The part where you look at a piece of code and can understand it as you read it vs figuring out where an expression or function starts and where it ends.



  • @stillwater said:

    Those things inside the square brackets are some kind of loop indexes thingy.

    Each of those terms in (loop [remaining-asym-parts asym-body-parts final-body-parts []] ... is a value that get passed between each iteration of the loop and its initial value in the first loop iteration. So remaining... starts off as the whole ...parts list and final... starts off empty.

    When recur is called, the loop starts over and the values passed to recur are the new values of those variables in the (loop [...] bindings.



  • @Bort said:

    (defn symmetrize-body-parts [parts]
    (vec
    (mapcat
    (fn [p]
    (let [mp (matching-part p)]
    (if (= p mp) [p] [p mp])))
    parts)))

    Much much much better. This feels so natural. So my example is a bit contrived then.Hmmm.



  • I already find everything is immutablezz cool and also enjoying the new found operator operand operand structure, destructuring pretty nifty fucking things until I got here to this example.



  • @Bort said:

    (defn symmetrize-body-parts [parts] (vec (mapcat #(set [% (matching-part %)]) parts)))

    This is no extra mental effort involved for you
    ? Does this actually feel 100% natural and smooth when you read it?



  • @stillwater said:

    Does this actually feel 100% natural and smooth when you read it?

    Does:

    for( int i = min_value; i <= max_value; i ++ ) {}

    ?

    I don't think the Clojure example is necessarily worse than that line of C.



  • Dumbest fucking comparison I've ever seen.


  • area_pol

    The problem may be that many of the contructs in this code are written with [ ] # % which are probably natural to the experienced users but incomprehensible to novices.



  • @stillwater said:

    Does this actually feel 100% natural and smooth when you read it?

    No, but... its natural compared to what? Compared to the C#? Let me try to write it in C#...

    // the MatchingPart function is given
    
    class BodyPart
    {
        public BodyPart(string name, int size)
        {
            Name = name;
            Size = size;
        }
        string Name { get; set; }
        int Size { get; set; }
        bool Equals(Object o)
        {
            var that = o as BodyPart;
            if (that == null) return false;
            return this.Name == that.Name && this.Size == that.Size;
        }
        // might also want HashCode() and == and != and IEquatable<BodyPart>, blah blah blah
    }
    
    IEnumerable<BodyPart> SymmetrizeBodyParts(IEnumerable<BodyPart> parts)
    {
        return parts.SelectMany(p =>
        {
            var mp = MatchingPart(p);
            if (p.Equals(mp))
            {
                return new [] {p};
            }
            return new [] {p, mp};
        });
    }
    

    ...yes, I prefer the Clojure.

    But of course I wrote it in the same idiom as Clojure, so duh Clojure works better for that.

    I didn't even want to think of it in terms of a mutable list. I've become very unaccustomed to that.



  • @stillwater said:

    (defn matching-part
    [part]
    {:name (clojure.string/replace (:name part) #"^left-" "right-")
    :size (:size part)})

    This could be written like this:

    (defn matching-part [part]
      (update part :name #(clojure.string/replace % #"^left-" "right-")))
    


  • Okay I'll rephrase myself. I am not blaming the clojure syntax necessarily.

    1. f(g(x)) seems okay
      2.f(g(h(I(x)))))))))))))) seems a bit hard to comprehend.


  • @Bort said:

    defn matching-part [part]
    (update part :name #(clojure.string/replace % #"^left-" "right-")))

    Yup this is much easier. I wanna know how clojure is written professionally. Is this style preferred over the other one liner? Or the one liner the more clojurish way of wrting things?



  • Wow shit! Having dabbled in clojure for quite some time, C# looks soooooo verbose in comparison!



  • @stillwater said:

    Dumbest fucking comparison I've ever seen.

    How is a raven like a writing desk?



  • @stillwater said:

    f(g(h(I(x)))))))))))))) seems a bit hard to comprehend.

    I totally agree. It's become the sanctioned style to put all the parens at the end like that instead of the trailing staircase that we're used to in C languages.

              }
            }
          }
        }
      }
    }
    

    Pssst... (-> x l h g f)

    Psssst psssst... ((comp f g h l) x)



  • Yes


  • Trolleybus Mechanic



  • @blakeyrat said:

    How is a raven like a writing desk?

    Do tell


  • FoxDev

    Because it can produce a few notes, tho they are very flat; and it is nevar put with the wrong end in front!


  • Discourse touched me in a no-no place

    @swayde said:

    @blakeyrat said:
    How is a raven like a writing desk?

    Do tell

    Neither one can whistle.



  • @swayde said:

    Do tell

    You need to go read the classics.


  • Trolleybus Mechanic

    @swayde said:

    @blakeyrat said:
    How is a raven like a writing desk?

    Do tell

    Both result in severe dick injury when you fuck them.



  • @swayde said:

    @blakeyrat said:
    How is a raven like a writing desk?

    Do tell

    "Poe wrote on both" is my favourite answer.



  • Not a reference to Alice?


  • Trolleybus Mechanic

    @swayde said:

    Not a reference to Alice?

    Chapter 37
    Alice squirmed on the writing desk, her legs spread wide, her pinafore hiked up to her thighs-- already soaked.

    "Take me, Mr. Raven," she breathed with a quiver, "Just like you would this writing desk."

    She locked eyes with her lover. "Eat me."


  • FoxDev

    @Lorne_Kates said:

    Chapter 37Alice squirmed on the writing desk, her legs spread wide, her pinafore hiked up to her thighs-- already soaked.

    "Take me, Mr. Raven," she breathed with a quiver, "Just like you would this writing desk."

    She locked eyes with her lover. "Eat me."

    @accalia wants to read the other 36 (or more) missing chapters of that story.


  • FoxDev

    @RaceProUK wants @accalia to send the chapters her way when she's done with them



  • @Bort said:

    (defn matching-part [part]
    (update part :name #(clojure.string/replace % #"^left-" "right-")))

    @Lorne_Kates said:

    "Take me, Mr. Raven," she breathed with a quiver, "Just like you would this writing desk."

    She locked eyes with her lover. "Eat me."

    How did this even get from there to here ? I don't even....


  • :belt_onion:


  • Notification Spam Recipient

    @RaceProUK said:

    @RaceProUK wants @accalia to send the chapters her way when she's done with them

    @Tsaukpaetra attempted to content-match the source post and failed.

    Closest match (Edit: NSFW, obviously): www.asstr.org/~ingrid/ossified-alice.html
    Details: 4 chapters, ~16k words.



  • Hey guys,

    What about Scala? How far down the rabbit-hole do you have to go to make it worthwhile?



  • All I know about clojure's what ive read in this thread, plus a quick google to find out how to comment in it, but here are my thoughts after trying to figure out wtf is going on:

    ;function “def'nition”
    (defn matching-part
    ;are we passing deafen an array of tokens here, or is this an entirely different thing that uses the exact same syntax as array literals? Can't figure out which option would be more lispy
      [part]
    ;anonymous object creation. Personally I prefer it when the colon is at the right.
    ;and wtf is up with the slash?
      {:name (clojure.string/replace 
    ;is hash a macro that turns a string into a regex? Is that why they got rid of string.replaceAll?
          (:name part) #"^left-" "right-")
    ;and please tell me there's a macro for getting object members using dot notation
       :size (:size part)})
    
    ;why is this indented? Is it because you didn't know about ``` for code blocks?
        (defn symmetrize-body-parts
    ;now we're passing deafen a docstring as second parameter. Does clojure do overload resolution, or do you have to examine the value of each argument once it gets in to your function, like in javascript?
          "Expects a seq of maps that have a :name and :size"
    ;also, there's a thing I've been doing lately where every time I'm about to document something like this, I ask myself whether there's a way I could write that using language constructs instead. There's strong typing for the above, and annotations for most of the rest. I guess lisp just isn't expressive enough for stuff like that.
          [asym-body-parts]
    ;looks like loop takes an array of [token value token value] when it could just as easily taken an array of tokens followed by an array of initial values, or just an array of actual pairs. Wilful.
          (loop [remaining-asym-parts asym-body-parts
                 final-body-parts []]
            (if (empty? remaining-asym-parts)
              final-body-parts
    ;I dont love destructuring, but I guess I'm gonna have to get over that. It's one of those ‘cool’ ‘new’ ‘features’ everyone seems to want in their language.
              (let [[part & remaining] remaining-asym-parts]
                (recur remaining
    ;why tf is the concatenation function called ‘into’?
                       (into final-body-parts
    ;now we're using the noun form of the word set, where every other function name's been a verb (or, inexplicably, a preposition).
    ;well, except matching-part, but that's stupidity on the part of a coder, not stupidity baked into the core library.
                             (set [part (matching-part part)])))))))
    


  • Nobody @mention‌ed me?
    I'm disappointed.


  • :belt_onion:

    @aliceif

    Also, congrats on the promotion!



  • I didn't realize you were interested in clojure.



  • @accalia said:

    @Lorne_Kates said:
    Chapter 37Alice squirmed on the writing desk, her legs spread wide, her pinafore hiked up to her thighs-- already soaked.

    "Take me, Mr. Raven," she breathed with a quiver, "Just like you would this writing desk."

    She locked eyes with her lover. "Eat me."

    @accalia wants to read the other 36 (or more) missing chapters of that story.

    "And in other news today, The Daily WTF is thrilled to announce its partnership with LitErotica for a series of collaborative articles on the fine border between coding and sex. Stay tuned for "A Touch And A Fsck" - the first story where a handsome IT administrator gives a young programming intern a lesson on Linux... and lovin'."


    Filed under: fine border, yeah, more like a fucking Maginot line



  • @Maciejasjmj said:

    border between coding and sex

    IOSYS Border of extacy – 04:19
    — Riki mtasu


    (Attention: contains lewd noises)



  • It seems like it could be interesting, I only skimmed over the braveclojure thing until the end of the page that code sample is on, though.



  • It is interesting. Unfucks your mind quite a bit

    5/10 would recommend halfheartedly.


Log in to reply