[HN Gopher] Why study functional programming? (2012)
       ___________________________________________________________________
        
       Why study functional programming? (2012)
        
       Author : arkj
       Score  : 113 points
       Date   : 2022-08-02 17:00 UTC (6 hours ago)
        
 (HTM) web link (acm.wustl.edu)
 (TXT) w3m dump (acm.wustl.edu)
        
       | globalise83 wrote:
       | I find it beautiful, especially recursion. The fact that you can
       | just let the computer take care of the problem in some strange
       | and invisible separate dimension is pretty magical to me.
        
       | procavia wrote:
       | At my university the first programming class that every CS major
       | had to take was functional programming. Many people would come in
       | with no experience and FP would be their first introduction to
       | the field. It was a very controversial course among students due
       | to its perceived usefulness (or lack thereof), but as someone who
       | already was familiar with imperative languages I really enjoyed
       | it.
        
       | anonimamente wrote:
       | Oftentimes we read a comment of the kind "bad or good code can be
       | written in any language or paradigm" in response to writings of
       | the ills or virtues of said language or paradigm. Thus implying
       | that we really shouldn't care of the choice of tools but rather
       | concern ourselves with the individuals using them? This seems
       | like an easy out. Too easy. If it is bad code that we need to
       | worry about, no matter what the syntax or semantics, then how do
       | we do that? Is bad code, like porn, something that we only
       | recognize when we see it, impossible to clearly define? If that's
       | the case, then we really need to figure out some better way to
       | guide us. The mention of Kevlin Henney is particular here in that
       | he has made presentations specifically identifying examples of
       | bad code and how they are made better. If no language or paradigm
       | can help steer us in the right direction--a proposition that I do
       | not believe--then there best be some clear way to tell us how to
       | avoid the pitfalls other than "I know it when I see it."
        
       | silent_cal wrote:
       | The problem with programming paradigms is that people tend to
       | follow them obsessively, to the point where breaking from the
       | paradigm seems automatically bad. For example, the four "pillars"
       | of OOP are kind of arbitrary in my opinion, so I don't see an
       | issue with breaking them, but sometimes writing a class is a
       | better way to handle a collection of inter-related variables &
       | functions. I don't think that makes me an OOP "adherent". It's
       | not really possible to determine a priori if one theory will
       | always be better than another when it comes to writing programs.
        
         | tomxor wrote:
         | Correct, more generally the problem is often absolutism, and
         | presenting or applying ideas as absolute truths.
         | 
         | All of the ideas have merit, they have cases where they work
         | wonderfully, and a lot of places where they do not. This issue
         | extends beyond programming patterns and paradigms, not only
         | into the rest of technology but life in general. You cannot
         | unsee this, you will start to see "worked for me"s being
         | presented as "this is the solution to all things" everywhere.
         | 
         | My first criticism to observation based conclusions anyone
         | suggests is usually "that's subjective" and the following
         | criticisms are usually exploring the parameters of that
         | subjectivity, my partner is so tired of me saying this, because
         | everything is subjective - I shouldn't need to say it, but we
         | seem to live in a world where it's increasingly necessary to
         | point out.
        
         | danielvaughn wrote:
         | Agreed. My favorite example of this is domain-driven design. I
         | _love_ the core concepts - get everyone on the same language,
         | make sure the code follows directly from business rules, etc.
         | But you open the book and it 's a flurry of absurd terminology
         | that does nothing but obfuscate whatever the author is trying
         | to talk about.
         | 
         | Then that terminology gets tossed around by hardcore adherents,
         | and you end up more confused about software development than
         | before you learned about DDD. It's a shame.
        
           | silent_cal wrote:
           | It may be because programmers are often also attracted to
           | mathematics, and so they think everything in programming must
           | be very carefully defined, and everything must follow from
           | axioms. In reality, programming has a lot more in common with
           | a practical skill like carpentry - you use the best tools &
           | methods available depending on the product you're trying to
           | make.
        
             | edgyquant wrote:
             | Funny you chose carpentry which is very much a field where
             | everything must be mathematically tested and proofed.
        
       | dboreham wrote:
       | Obvious reason to study FP is: when, inevitably, someone appears
       | who believes they are smarter than you due to their love of FP,
       | you can more effectively defeat them.
        
         | Traubenfuchs wrote:
         | In such a situation you can also chose not to engage. The FP
         | nerd might perceive this as you giving up, but a strong, mature
         | personality like yours allows you to know you are the true
         | winner.
        
           | harveywi wrote:
           | Wanderer: What is the secret to eternal happiness?
           | 
           | Guru: To not argue with fools.
           | 
           | Wanderer: I disagree.
           | 
           | Guru: Yes, you are right.
        
             | b5n wrote:
             | > Sometimes I just agree with people so they can stop
             | talking.
             | 
             | - Jet Li
        
         | filoleg wrote:
         | This is so true, it hurts.
         | 
         | From my personal (and rather limited) experience, there are two
         | kinds of people who are into FP. First are those who will act
         | like christian missionaries or competitive vegans and tell you
         | all about it in the most obnoxious way possible every time they
         | see you. And the rest are those who you wouldn't even know are
         | into FP.
         | 
         | Obviously exaggerating for a comedic effect here, as there are
         | a few people in the middle. But the median of my personal
         | experiences is definitely very well described by just those 2
         | commonly present types above.
         | 
         | You joke, but your "to shut the obsessed ones down easier"
         | reasoning for getting into FP was one of my primary reasons for
         | doing the same (along with just actually liking FP paradigms
         | and learning quite a bit of cool stuff from it).
        
           | magicalhippo wrote:
           | Being self-taught, once we got internet back in the days I
           | spent a lot of time on IRC for help with programming. As I
           | grew more experienced I spent a _lot_ of time on IRC helping
           | others.
           | 
           | After a decade or so, I formulated a theory based on my
           | myself and those I helped on IRC. It seemed many (most?)
           | programmers starting out followed a similar trajectory where,
           | as they became competent programmers and grew confident in
           | their skills, would latch on to some way as _the_ way.
           | 
           | Then, over time, as they got a lot more experience, they'd
           | realize that often there are many different approaches with
           | different merits and tradeoffs, and not get so dismissive to
           | other approaches.
           | 
           | Could it be your "two kinds" are those that just became good
           | at FP, and those that have been good at it for a while and
           | grown in experience?
           | 
           | Anyway, not saying this is any profound insight, just
           | something that struck me at some point during my journey.
           | 
           | edit: Not all would grow beyond that initial stage. Some
           | plateaued shortly after. But for myself and many of those I
           | followed over time seemed to fit this.
        
             | q7xvh97o2pDhNrh wrote:
             | I learned a ton through IRC, too! And I'd give a strong +1
             | for this pattern. Personally, I think it applies generally
             | to a lot of fields. Once someone has sufficient experience
             | and wisdom, they inevitably come face-to-face with how
             | little they truly know.
             | 
             | Ideally, that humility is paired with a general sense of
             | wonder and curiosity. I think, once you realize how little
             | you know, it gets so much easier to (re)embody the
             | childlike curiosity and desire to learn more. I don't think
             | it's a given, though -- and sometimes (at the risk of
             | arrogantly declaring myself to be humble), I find it pretty
             | hard not to be overwhelmed by the massive volumes of
             | reality that I'll never get to learn about.
             | 
             | William Butler Yeats had a slightly different -- but far
             | more beautifully phrased -- take on it in his poem, _The
             | Second Coming_ : [1]                 The best lack all
             | conviction, while the worst          Are full of passionate
             | intensity.
             | 
             | [1]: https://www.poetryfoundation.org/poems/43290/the-
             | second-comi...
        
         | peoplefromibiza wrote:
         | I admit I laughed at this!
         | 
         | Whatever is the motivation, I'll say that the more people learn
         | FP the better.
         | 
         | It won't hurt.
        
         | [deleted]
        
         | thankful69 wrote:
        
       | serde111 wrote:
       | If you learn FP, in a real FP language, it will bring discipline
       | into the way you write code. All code you write, once you "get
       | it", functional or non-functional may become an order of
       | magnitude better.
        
       | [deleted]
        
       | tresqotheq wrote:
       | Because Haskell is awesome, and if you want to code in Haskell,
       | you need to grok functional programming.
        
       | tpoacher wrote:
       | I have a feeling the term "functional programming" will be a
       | negative term by the end of the decade.
       | 
       | Not "functional aapproaches", just "functional programming".
       | 
       | In the same way that now "Object-oriented programming" is a
       | negative term (but OO techniques in isolation where appropriate
       | by context are totally fine).
        
         | jacquesm wrote:
         | > I have a feeling the term "functional programming" will be a
         | negative term by the end of the decade.
         | 
         | And what do you base this feeling on?
         | 
         | Functional programming has been on a very slow and steady rise
         | since... the 1950s. In fact the site that you are writing this
         | on is written in a functional programming language.
        
           | baby wrote:
           | slow and steady doesn't win the race :p I think FP would have
           | to get big before getting any bad rap, and I don't think it
           | will
        
             | jacquesm wrote:
             | FP has a lot going for it and it is gaining traction bit by
             | bit in all kinds of domains where previously this was not
             | the case.
             | 
             | I'm not sure if we should lump Erlang/Elixir in with
             | functional programming (I think they should be but others
             | may disagree because of the Prolog ancestry), but Clojure
             | is definitely there as is Haskell, F# and so on.
             | 
             | Reliability in software is rapidly becoming a key item, as
             | more and more real world processes are directly influenced
             | by software accidents have the potential to have very bad
             | consequences, and functional programming is very good at
             | completely avoiding certain classes of bugs. Couple that
             | with mature eco systems and success stories such as
             | WhatsApp and I think we are getting closer to seeing FP
             | become mainstream.
             | 
             | What really would move the needle is if software
             | engineering were to be held to the same standard as regular
             | engineering: liability. Sooner or later this industry will
             | have to grow up and all the band-aids in the world won't
             | help to achieve that if it isn't addressed at the
             | foundation.
        
       | eatonphil wrote:
       | I think the best reason to study FP is to get out of the OOP
       | mindset.
       | 
       | But ideally in the real world you don't go crazy with either.
       | 
       | Objects are excellent for data but OOP is a mess for control
       | flow.
       | 
       | Immutability is great but everything-is-recursion is not.
       | 
       | And so on.
       | 
       | When performance comes up all of this goes out of the window,
       | maybe. But I'm talking about good defaults for correct, readable
       | programs.
        
         | kalekold wrote:
         | > I think the best reason to study FP is to get out of the OOP
         | mindset.
         | 
         | > Objects are excellent for data but OOP is a mess for control
         | flow.
         | 
         | http://nomad.uk.net/articles/developers-who-hate-on-oop-don'...
        
           | cardanome wrote:
           | > If OOP is causing complexity in your program it's either
           | the wrong tool for the job or you are using it poorly.
           | 
           | No.
           | 
           | The whole point about OOP is that it increases complexity. It
           | uses higher levels of abstraction to organize the program.
           | 
           | Sure you might end up with a program that is possibly easier
           | to understand and maintain and maybe even shorter but always
           | more complex than the strict procedural equivalent. Simply
           | cause you increased the levels of abstractions one needs to
           | go through to understand the program.
           | 
           | That is, of course, not OOP specific. Introducing any form of
           | abstraction introduces extra complexity. If you use the
           | abstraction right, the problem becomes easier to handle but
           | you always pay a cost.
           | 
           | Though the have a point with
           | 
           | > If you have used OOP well and the program still turns out
           | more complicated than if it was written in a procedural style
           | then you may as well use procedural code.
           | 
           | The art of software engineering is finding a level of
           | abstraction that is appropriate for the complexity of the
           | problem that is to be solved. Don't over-engineer but also
           | don't under-engineer your software.
        
         | pdpi wrote:
         | Funnily enough, I disagree -- I find that the overwhelming
         | majority of problems with OOP come precisely from trying to use
         | it with data. The only thing it's good for is precisely control
         | flow at the macro level.
        
           | eatonphil wrote:
           | We'll just have to agree to stay away from each other's code.
           | :)
        
         | guelo wrote:
         | One of the bigger advantages of OOP that I rarely see discussed
         | is the natural namespacing that you get. In other paradigms you
         | end up polluting the global namespace more easily, harming
         | autocompletion and discoverability.
        
           | pharmakom wrote:
           | Most FP languages have modules so not sure where this idea
           | comes from.
        
         | jrvarela56 wrote:
         | | Objects are excellent for data
         | 
         | Check out DOP
         | https://blog.klipse.tech/dop/2022/06/22/principles-of-dop.ht...
         | and Rich Hikey's critique of OOP (~'objects are custom
         | languages on top of data'; they force you to learn specific
         | semantics to manipulate plain data structures and make it tough
         | to reuse your code).
        
           | dkarl wrote:
           | > Objects are excellent for data
           | 
           | Objects are great for modeling data as long as you still
           | think of it as data, and you can write good data processing
           | programs using OO language constructs.
           | 
           | OOP as an approach to programming gets it backwards, though.
           | OOP encourages you to think of the objects as primary and the
           | data representing them (on the wire, in a datastore) as a
           | secondary, inferior manifestation. This is the opposite of
           | true. The software's value is created by its handling of data
           | on the wire, reading data from other systems and writing data
           | to other systems. OOP objects provide no value except by
           | reading and writing data. If you start believing that the
           | objects provide the value and the data exists to support the
           | objects, as OOP encourages, then you start to suffer from all
           | kinds of delusions.
        
             | lostcolony wrote:
             | Once you start thinking that way, you start wondering why
             | Objects, rather than (from Java) records, or (from most
             | every other language) structs/tuples.
             | 
             | That is, why bundle functions with the data and encapsulate
             | it as a new type that ties them together? It invites the
             | very thing you're saying not to do; if you want to think of
             | it as just data...then make it just data. Nouns only; no
             | verbs. Even if you have a verb as data, treat it as a noun
             | (i.e., a higher order function).
             | 
             | It's all translatable; you can break an object into
             | functions and data, and create an object bundling functions
             | and data, but, as you say, it's about how you think...and
             | objects do not encourage you to think about the underlying
             | data, but about the abstraction. And abstractions are
             | leaky, don't translate well into new domains, and are much
             | harder to communicate (both at an API level and between
             | humans) than data.
        
           | vkou wrote:
           | The semantics of objects are pretty straightforward, but the
           | assurances that they provide on top of your data is their
           | main value add in this context.
           | 
           | Yes, things like protobufs, or equivalents thereof provide
           | you with a list of auto-generated low-level assurances, but
           | there are often bits of non-trivial business logic about data
           | modification/reading that cannot be easily expressed outside
           | of a object implementation in a Turing-complete language.
           | 
           | They also clearly express a concept of, and when used
           | correctly, boundaries for data ownership, which for non-
           | ephemeral data can be important.
        
           | jcelerier wrote:
           | > (~'objects are custom languages on top of data';
           | 
           | how is that a bad thing - that's literally the point of the
           | activity of programming, creating domain-specific
           | sublanguages to manipulate data in a way that is readable by
           | domain experts of this specific data
        
             | jrvarela56 wrote:
             | The argument is that this default forces you into creating
             | DSLs for basic data manipulation (it's all [] and {} in the
             | end).
             | 
             | You end up with 'custom' logic with custom naming that
             | increases the overhead of using your codebase. That's a
             | long way of saying your code is less reusable.
             | 
             | In DOP/FP land, you create functions to manipulate basic
             | data types and your domain-specific knowledge ends up
             | encoded as basic data types (say you want validations on a
             | model, you'd encode those as a {} and create functions to
             | validate vanilla []/{}).
        
         | oxff wrote:
         | > Objects are excellent for data
         | 
         | They are not. If your data is in objects, you have already
         | demoted data as a first class member of your language (ie.
         | Java)
        
         | rr888 wrote:
         | > OOP is a mess for control flow.
         | 
         | I used to think this until my new project where everything is
         | functional, everything is reactive, everything is a lambda.
         | Each function is very simple but the whole thing is impossible
         | to trace.
        
           | freedomben wrote:
           | I've seen functional code like that as well, and it's truly
           | awful. If all FP was that way I'd avoid touching it with a
           | 1,000 foot pole. Most of the time though it's a developer who
           | writes bad code no matter which language/paradigm they're in,
           | but FP does give them tools to make it even more unreadable
        
         | bitL wrote:
         | Immutability is slow, so if you are somebody squeezing the
         | maximum FLOPS out of a CPU, you might want to stay away (sorry,
         | 1.3x slowdown in your best case is not acceptable, and "leave
         | it out to the compiler" is not a valid argument).
         | 
         | It's like with project management - the iron triangle of speed,
         | quality, price, pick two. With each programming paradigm you
         | pick a different set of attributes that might or might not be
         | the best for what you need and they enable you on one thing and
         | constrain you on another thing.
        
           | duped wrote:
           | Immutability is an API not an implementation. Immutable code
           | often outperforms mutable, it depends on the use case.
        
             | bitL wrote:
             | There is often some "redefinition of terms" going on with
             | dedicated functional programming folks in order to assert
             | their claims as you just demonstrated. There was some
             | benchmark where mutable Java was shown to be around 30x
             | faster than immutable OCaml and the discussion went to
             | something like "no, no, that's a wrong comparison, compare
             | it with immutable vs mutable OCaml, that is then just 2x
             | slower! And the next compiler revision will remove it! 100%
             | sure about it!" etc.
             | 
             | Why can't other modes of thinking coexist with your view?
             | FP is OK, so is OOP, so is imperative, low-level machine
             | code, "loop programs" (see Dennis Ritchie dissertation),
             | logic programming etc. I like them all but hate it when
             | somebody tries to push me one way telling me all other ways
             | are wrong.
        
               | mrkeen wrote:
               | Awesome, I'd love to read it!
        
               | freedomben wrote:
               | > _Why can 't other modes of thinking coexist with your
               | view? FP is OK, so is OOP, so is imperative, low-level
               | machine code, "loop programs" (see Dennis Ritchie
               | dissertation), logic programming etc. I like them all but
               | hate it when somebody tries to push me one way telling me
               | all other ways are wrong._
               | 
               | Why do you think GP is saying or doing that? I think
               | you've put a _lot_ of words into their mouth that aren 't
               | there, and then got yourself worked up about it, enough
               | to accuse them of ignorance and small-mindedness (at
               | best).
               | 
               | I see absolutely nothing in their comment that even
               | weighs in favor of FP, let alone saying other modes of
               | thinking can't coexist. For all we know GP is a rabid OOP
               | fan but sees the value in immutability (which FP
               | certainly does not have a monopoly on).
        
               | bitL wrote:
               | OK, my apologies, that comes as a baggage from previous
               | discussions with FP experts that routinely dismissed any
               | opposing ideas and the OP's answer struck the same chord.
        
           | freedomben wrote:
           | Immutability can be fast or slow depending on the
           | implementation. There are tons of copy-on-write
           | implementations that blaze past mutable implementations. When
           | the compiler knows that a particular variable/piece of data
           | will never be changed, it opens up a ton of optimizations
           | that can be used to make it fast. With mutable memory it's on
           | the developer to optimize, rather than the compiler. Most of
           | the time, the latter is better at it.
        
             | guelo wrote:
             | The problem is that developer has no idea if the
             | implementation is going to be performant for their use
             | case. The mutable compilers normally have less magic and
             | thus are easier for the developer to understand and
             | optimize. FP is really just a higher level language, that's
             | why they don't teach algorithms classes using FP languages.
        
             | bitL wrote:
             | With infinite memory and "no cost memory allocation" you'll
             | be likely correct, but in real world production loads
             | you'll hit those limits quickly and then the immutability
             | is likely getting in the way. Imagine just keeping a large
             | (possibly compressed) bitmap (TBs in memory) to keep track
             | of subscribers in your queue which is what many distributed
             | queues use - how would you do it in immutable fashion? Copy
             | the whole bitmap on each small change? There are simply
             | many problems where immutability is the wrong answer if you
             | want anything resembling performance.
        
               | freedomben wrote:
               | Absolutely, that would be one of the cases where "most of
               | the time" is not "this time." Although for most
               | developers/applications, I would imagine keeping TBs of
               | bitmap in memory isn't a common task. Fetching some rows
               | from the DB and transforming them into some sort of HTML
               | or JSON probably is
        
         | cpursley wrote:
         | Just don't make the mistake of studying FP first...
         | 
         | I can't seem to wrap my head around OOP. There's too many
         | concepts in OOP. In FP it's just data and functions for
         | transforming that data.
        
           | magicalhippo wrote:
           | > In FP it's just data and functions for transforming that
           | data.
           | 
           | In OOP it's just data and methods for manipulating that data.
        
           | Floegipoky wrote:
           | I started with mainstream procedural and OO languages like
           | C++ and Java. I felt like I had a pretty good understanding
           | of OOP by the time I left university. Later, learning a
           | little about FP took my OOP to a whole new level. I really
           | recommend reading Sussman and Steele if you haven't already,
           | it's basically a constructive proof showing how to represent
           | objects in a functional language. Unfortunately the title is
           | so boring that generations of CS undergrads skipped reading
           | the paper, so the zeitgeist forgot. Hewitt was another
           | important researcher at the MIT AI lab at that time credited
           | with discovering the Actor Model, which basically combines
           | objects with a concurrency model. I've seen him post on HN
           | occasionally =)
           | 
           | So many people think "OOP == classes", and I think it's
           | really a shame that (in many ways superior) alternative
           | representations were relegated to the sidelines for so long.
           | I see Java's relatively recent inclusion of algebraic
           | datatypes as a tacit admission that contemporary computing
           | requires different primitives, and I expect to see a shift in
           | best practices towards objects represented as immutable data
           | structures combined with effectively-pure functions. Just
           | like the FP folks have been saying all along!
           | 
           | > This work developed out of an initial attempt to understand
           | the actorness of actors... Sussman suggested the experimental
           | approach of actually building an "ACTORS interpreter"... When
           | it was completed, we discovered that the "actors" and the
           | lambda expressions were identical in implementation.
           | 
           | https://dspace.mit.edu/handle/1721.1/5794
        
           | bitL wrote:
           | Can you explain monads to a 5-year old? Can you explain
           | objects?
        
             | unsafecast wrote:
             | Yes, I can definitely explain monads to a 5-year old.
             | 
             | See, a monad is like a box. You can put something in the
             | box and close it very easily. But once it's closed, you
             | can't open it anymore. The action of closing the box is
             | called the wrap operation.
             | 
             | What you _can_ do though, is tell someone else to do
             | something to the thing inside the box. For example, if you
             | put a toy in and close the box, you can ask a friend to go
             | ahead and add a new one in. Or remove the toy. These are
             | monadic functions.
             | 
             | That's it. That's literally it. It's just a pattern of
             | hiding the data and letting monadic functions be the only
             | ones that deal with it.
             | 
             | In the case of the Maybe monad for example, you'd have the
             | unwrap function that tries to get whatever is inside out,
             | but it might not be able to (if the box is empty).
        
               | taeric wrote:
               | Not going to lie, I don't understand that explanation. It
               | honestly sounds more like you are describing a form of
               | encapsulation, as the contents of the box are hidden and
               | someone else has the ability to open said box to get
               | access to it.
               | 
               | I also find the appeal to a physical object to explain a
               | functional concept is rather amusing.
        
               | ModernMech wrote:
               | > I also find the appeal to a physical object to explain
               | a functional concept is rather amusing.
               | 
               | The challenge was to describe it to a 5 year old. 5 year
               | olds are better with concrete thinking than abstract
               | reasoning. This is what made using the turtle in Logo a
               | genius move, as it allowed younger children to write
               | programs by conceptualizing a physical turtle that can
               | move, rather than thinking in terms of an abstract
               | function that mutates data.
        
               | taeric wrote:
               | Fair, and I don't necessarily disagree. I think this
               | leads rather close to object oriented software being
               | easier to reason about concretely than functional
               | programming, though. And since most people are trying to
               | get a concrete job done, that feels like a significant
               | claim.
               | 
               | For turtle geometry, it is also important to acknowledge
               | the metaphor and shortcomings of a more traditionally
               | analytic framing of drawings. Specifically, X and Y
               | coordinates for a drawing are surprisingly hard to work
               | with. For example, I challenge you to describe the
               | fractal snow flake in an easier way than using directions
               | as a metaphor. Same for the dragon curve. This can be
               | seen akin to picking a different coordinate system, I
               | presume?
        
               | solomonb wrote:
               | Not sure if you are looking for an explanation of Monads,
               | but Monad tutorials are a long running joke in the
               | haskell world. They are almost exclusively written by
               | people for whom the concept just clicked and they either
               | fail provide context for someone without that experience
               | or they fail to actually describe the concept correctly.
               | 
               | I'm not gonna give you an explanation but I will say that
               | IMO the best way to actually learn about them is to just
               | look at the typeclass and a bunch of instances of it and
               | how they are used. If you ignore all the theory (and the
               | "theory") and just look at the code you will find that
               | they aren't that hard to sort out from a usage
               | perspective.
        
               | taeric wrote:
               | Apologies, I seem to have deleted a sentence where I
               | think I can make my understanding fit that metaphor. I
               | don't think they are completely unapproachable, but I am
               | not at all clear that a physical metaphor works. And, I
               | really wanted to shine a light on the amusing appeal to
               | physical objects in a thread that is about the short
               | comings of object oriented programming. :D
        
               | solomonb wrote:
               | No need for apologies! I 100% agree that the physical
               | metaphor doesn't work and said so in another nearby
               | comment.
               | 
               | If you go back to Phil Wadler's original paper on
               | implementing monads in haskell, he doesn't talk about
               | category theory or boxes or anything. He lays out a
               | handful of common things you might do in programming but
               | which seem totally unrelated. For each one he implements
               | a solution and then reveals that all these solutions fit
               | the same interface.
        
               | solomonb wrote:
               | Unfortunately the container metaphor only works for a
               | subset of monads. It fails with `IO`, `Reader`, `Writer`,
               | `State`, `Parser`, etc.
        
               | peoplefromibiza wrote:
               | how about we call the box wrapper and the operations on
               | it computations?
               | 
               | metaphors are good for beginners, to grasp the concept,
               | they don't need to be perfectly valid.
               | 
               | for example the popular OOP metaphor a car is a vehicle
               | becomes useless pretty much immediately.
        
               | solomonb wrote:
               | IMO the metaphor is already getting too frayed at this
               | point.
               | 
               | I'm not opposed to metaphors in general, but metaphors
               | are lot like abstractions. If you don't get the right one
               | then the details leak everywhere and you may as well have
               | not used it to begin with.
        
               | AnimalMuppet wrote:
               | Well, for IO, it seems to me that maybe it still works.
               | You're putting the entire external world in the box, but
               | you're still (kind of?) doing the same thing.
        
             | solomonb wrote:
             | I don't think that is a fair comparison. Monad is a
             | typeclass so it would be like explaining some specific Java
             | Interface (and all the context for Interfaces) to a 5 year
             | old.
             | 
             | The Haskell (since you brought up Monads) equivalent to
             | explaining Objects would be like explaining Records or Sum
             | types, which would be very easy to explain and don't
             | require talking about inheritance like Objects would.
        
             | mejutoco wrote:
             | I'll try.
             | 
             | A monad is a description of actions to do and their order,
             | in place of the actual actions. This description can be
             | passed around and eventually acted upon.
             | 
             | Objects (not Alan Kay's original ones but say Java) are
             | abstractions that model state and behaviour together.
             | Objects can share common behaviour through interfaces
        
             | freedomben wrote:
             | I don't know if you're being serious or not, but you can
             | learn a ton of FP without having to understand monads. Also
             | asking to explain "objects" is too ambiguous. an "object"
             | in json is very simple. OOP on the other hand involves a
             | mountain of different concepts, design patterns, best
             | practices, etc. I would guess GP is referring to that
             | stuff.
        
               | LudwigNagasena wrote:
               | You can learn a ton of OOP without having to dive into a
               | mountain of different concepts too.
        
               | pmontra wrote:
               | You can write OOP code without knowing a single pattern
               | and whilst laughing at Factory classes you read in
               | someone else's code. You might have to reinvent the wheel
               | sometimes and face some difficulties talking with people
               | that know every single pattern.
               | 
               | And there are best practices for every single language
               | and paradigm.
        
             | mdcds wrote:
             | I heard following explanation of monads somewhere online:
             | _" monads allow us to write imperative code in the
             | functional setting. e.i. chain computations"_.
             | 
             | But that explanation wouldn't make sense to a 5-year-old
        
             | peoplefromibiza wrote:
             | monads are a very simple pattern
             | 
             | it takes 5 minutes to understand it, the jargon is complex,
             | the implementation is not.
             | 
             | case in point
             | 
             | https://youtu.be/C2w45qRc3aU
             | 
             | objects are a very leaky abstraction that usually brings
             | people to build taxonomies, mostly unrelated to the parent.
             | 
             | reuse of code, which is the selling point of OOP,also comes
             | often short with a miriad of very specialized subclasses
             | that have nothing in common anymore.
             | 
             | OOP is not horrible, but it requires a good amount of
             | discipline to get it right, while FP has less concepts and
             | you can (usually) silo the "and now for the tricky bits"
             | (cit. Robert Virding) in a small core.
             | 
             | the rest is simple pure functions that have also the
             | benefit of being stupid trivial to test.
             | 
             | Also, you don't have to be purely functional nowadays, and
             | that helps a lot.
             | 
             | If only I learned FP sooner, my life as a programmer would
             | have been so much better.
        
               | freedomben wrote:
               | You're point about testability is a good one that I feel
               | is often missed. Trying to test functions in OOP code is
               | often impossible because they presuppose some state in
               | the "object" and if it's not initialized properly, it
               | doesn't work. Then they also often make side effects. So
               | you end up building a huge test harness to build up some
               | state, run one test, and tear it all back down again only
               | to rebuild it from scratch for the next test. It's doable
               | of course, but it's easy for a simple CRUD app to have a
               | 15 minute test suite and for tests to become flaky
               | because of some unexpected state change done in some
               | unrelated test on the other side of the code base. That's
               | a special form of hell
        
               | goostavos wrote:
               | Monads are indeed way simpler. Just a few beautiful laws.
               | The problem is that they take a loooooooooooong time to
               | really internalize. Saying it takes "5 minutes" is empty
               | in the same way that "learn C++ in 24 hours" claims are
               | (or you're hella smart!).
               | 
               | There's a quote that floats around that's like "as soon
               | as you understand monads, you lose the ability to explain
               | monads." It takes a ton of leg work to make them click.
               | They're simpler, but definitely not easy (in the Rich
               | Hickey sense).
        
               | bitL wrote:
               | Ok, so you understood flatmap and therefore monads in 2
               | minutes. Now you need something that needs nested monads.
               | That's where major complexity suddenly appears - your
               | code is no longer simple and is full of artificial
               | constructs like transformers just to do simple things.
               | Moreover, anyone who reads your code must know all
               | language constructs you are using or they are lost and
               | can't fix any issue in your code.
        
               | solomonb wrote:
               | > Moreover, anyone who reads your code must know all
               | language constructs you are using or they are lost and
               | can't fix any issue in your code.
               | 
               | Does this not apply to every language ever?
        
               | peoplefromibiza wrote:
               | 5 minutes is the time it takes to understand how the
               | pattern works.
               | 
               | Be good at it?
               | 
               | More like a thousand hours.
               | 
               | there is nothing that is really simple, but before being
               | simple, everything looks difficult.
               | 
               | p.s. I love Rich Hickey and especially his keynotes at
               | Clojure conferences.
               | 
               | I've watched simple made easy at least 10 times.
        
           | trebbble wrote:
           | > I can't seem to wrap my head around OOP. There's too many
           | concepts in OOP.
           | 
           | Which ones? You're familiar with structs, right? OO is just
           | structs with a little magic & sugar. Not even that much.
           | Objects, methods, properties, instances, classes:
           | 
           | Imagine if, when defining a struct type, you could put
           | references to functions on it, such that any struct of that
           | type would contain those same fields with references to the
           | same functions you put in the type definition. Then, if you
           | create a struct of that type, the compiler and/or runtime
           | will helpfully and magically appends an extra argument to
           | those function signatures, assigning it some conventional
           | name ("this", perhaps) and, if you call such a function "on"
           | a struct of that type, the compiler/runtime will quietly, in
           | the background, pass a reference to the struct you called the
           | function "on" in that last argument slot, so that within the
           | function you can make use of the function's "parent" struct
           | (as, perhaps, a variable named "this").
           | 
           | The struct type with slightly-magical function references is
           | a class.
           | 
           | The fields on the struct containing references to functions
           | with the magical "this" argument appended when invoked, are
           | methods.
           | 
           | A struct of that struct-type is an object, or _instance_ of
           | the struct type, if you will.
           | 
           | Fields on the struct are properties or members or whatever
           | you like to call them.                   Static:
           | 
           | What if you could tell the compiler/runtime not to bother
           | appending that "this" argument to some of those functions you
           | attached to a struct type definition? Or to have a given
           | field on a struct type definition always point to the same
           | location for every single struct of that type, so that they
           | all essentially share a single variable? That's what "static"
           | means.                   Inheritance:
           | 
           | What if you could tell the compiler/runtime that it should
           | associate one or more other struct type definitions with the
           | struct type you're currently writing, and that if it can't
           | find a given field (including ones that are refs to
           | functions, aka methods) on a struct of this type, it should
           | check an associated struct of the other type(s) and only
           | error if it can't find it there, either. With the result that
           | a struct type so constructed effectively contains all the
           | fields of the structs associated with it, unless a duplicate
           | exists on that child struct type, in which case that takes
           | precedence.
           | 
           | That's basically inheritance. It's all about setting up and
           | manipulating those kinds of relationships & precedence for
           | lookups. That's all.                   Abstract, et c.:
           | 
           | Just ways to have the compiler enforce constraints and
           | requirements on a struct type definition.
           | Final
           | 
           | I do solemnly swear this is a constant, not a variable.
           | 
           | Now, there are implementation details under the hood for all
           | this, but that covers actual usage, terminology, and concepts
           | pretty well. You don't need to dig into the details of e.g.
           | vtables (one tool for efficiently settling those inheritance-
           | leveraging field lookups) unless you're implementing OO
           | itself.
        
         | kephasp wrote:
         | > _Immutability is great but everything-is-recursion is not._
         | 
         | Why oppose a real pattern and a imaginary one?
        
         | jstx1 wrote:
         | I mean there's other options too. Go for example is mostly
         | imperative(?) - it doesn't encourage heavy OOP or pure
         | functional programming. Rust has more functional features but
         | it's still neither purely functional nor heavily OOP. Julia
         | isn't OO at all but it doesn't emphasize FP either.
         | 
         | Those are just three languages that are all (1) modern, (2)
         | generally well received, (3) neither OO nor heavily functional
         | and (4) still very different from each other.
        
       | mikewarot wrote:
       | _The recent focus on adapting functional programming_ is a
       | reaction from the shift to the dangerous quadrant of the
       | immutable-mutable /unshared-shared "Magic Quadrant" chart.
       | 
       | Before multi-core, multi-threading, it didn't matter how or when
       | you decided to update your local variables, they were YOUR local
       | variables... unshared.
       | 
       | With threading, and multiple cores, we all just blindly moved
       | right to the mutable/shared quadrant... the one in bright red...
       | which effectively _changes the laws of physics_ of your programs.
       | Effectively every piece of code now runs in it 's own time and
       | space, and if you don't coordinate things correctly, it's like
       | killing your own grandparents.
       | 
       | It took me a long time to understand why you'd want to refactor
       | your code until everything was immutable[1], but now that I get
       | the lesson, its something I won't forget.
       | 
       | Functional programming avoids mutable data, and thus,
       | intentionally or not, works well in a world of shared data.
       | Because pure functions have no side effects, they are timeless -
       | they need no synchronization.
       | 
       | Spend a few nights watching everything Kevlin Henney has said in
       | the last few years, and you'll have a _much_ better handle on
       | things.                 [1] - https://youtu.be/APUCMSPiNh4
       | 
       | [Edit] Incorporate wording suggestion from DonaldPShimoda
        
         | badpun wrote:
         | I've worked in two functional codebases so far and I'd say that
         | in both cases the mutation of shared state was just moved to
         | database and its transaction semantics. The FP code itself was
         | about mostly stateless server-side processing. So, FP wasn't
         | doing anything for us on that front. The main selling point for
         | it was that it makes program more composable, more concise and
         | easier to refactor (as you're effectively working with higher-
         | level abstractions).
        
           | lostcolony wrote:
           | >> in both cases the mutation of shared state was just moved
           | to database and its transaction semantics. The FP code itself
           | was about mostly stateless server-side processing. So, FP
           | wasn't doing anything for us on that front.
           | 
           | Sure it was. While it didn't force devs to stop using mutable
           | state, you just called out that it -did- force them to move
           | that state out of the service and into something with ACID
           | guarantees, and write their server code in a way that was far
           | more stateless. That sounds like a win to me?
        
         | nine_k wrote:
         | Your global variables were / are shared with yourself, even in
         | no-concurrency case. With typical control flow being far from
         | linear, it's easy to surprise yourself with unexpected state
         | mutation.
        
           | Scarbutt wrote:
           | Hence the value of immutability even for single-threaded
           | code.
        
           | Jtsummers wrote:
           | Giving me flashbacks to inherited codebases from old-school
           | FORTRAN coders...                 // 500 variables shared by
           | everything       main loop         "task" 1         "task" 2
           | "task" 3         ...         "task" n
           | 
           | So _t121_ is now supposed to only be used by task 3, but  "t"
           | as a prefix means it is temp. However, we don't want to
           | change all the references. So just don't use it everyone
           | else, please?
        
           | MaxBarraclough wrote:
           | Right. Pure functions make it considerably easier to reason
           | about code, even in the absence of concurrency.
           | 
           | It's a shame D's _pure_ modifier (to statically guarantee
           | purity) isn 't available in many other languages. [0] SPARK
           | Ada has something similar in that functions must always be
           | pure, forcing procedures to be used for impure functionality.
           | [1] _edit_ I think that 's mistaken, SPARK appears to permit
           | functions to read globals but not to modify them.
           | 
           |  _edit_ John Carmack has written about this kind of thing.
           | From [2]:
           | 
           | > _if a function only references a piece or two of global
           | state, it is probably wise to consider passing it in as a
           | variable. It would be kind of nice if C had a "functional"
           | keyword to enforce no global references._
           | 
           | [0] https://dlang.org/spec/function.html#pure-functions
           | 
           | [1] https://learn.adacore.com/courses/intro-to-
           | spark/chapters/01...
           | 
           | [2] https://cbarrete.com/carmack.html
        
         | bitL wrote:
         | This resembles a situation when I got a new boss who once tried
         | to write a 2-threaded app and got burnt, so from then onward he
         | mandated to never use multiple threads (despite me using it
         | safely on 65000+ threads before). A better answer would be
         | "most devs aren't skilled enough to use many threads/mutable
         | shared objects, so lets mandate immutable for basic devs so
         | that they don't get burnt". But why would you prevent proven
         | experts from operating in the dangerous quadrant? Does
         | everything have to become dumb to make it safe?
        
           | jerf wrote:
           | That dangerous quadrant has a track record of chewing up and
           | spitting out "proven experts". I'd put your question in the
           | same class of question as "Look, I know memory management in
           | C is just dangerous, but do we have to make everything dumb
           | to make it safe?" False dichotomy; the solution to everything
           | isn't to "make it dumb", but the proven experts have a long
           | track record of being chewed up and spit out and the answer
           | isn't to tell them to just Git Gud either. We tried that. We
           | tried that a _lot_. It doesn 't work.
           | 
           | The solutions to concurrency pretty much all involve staying
           | out that quadrant as much as possible. Immutability isn't the
           | only solution. Another is to confine all variables to one
           | thread. Erlang, for instance, superficially uses immutability
           | to achieve this, but a deeper reason it achieves it is that
           | there is simply no way for a "thread" (what Erlang calls
           | "process") to modify a variable that another thread can see;
           | this is sufficient. (See what Elixir does.) Rust implements a
           | super-rich system of variable ownership that allows you to
           | implement the constraint that no variable can be unexpectedly
           | just modified by an arbitrary thread in a far richer fashion
           | than just hard-locking all memory to a particular owner
           | thread. This is also sufficient. I program a lot in Go, and
           | while it lacks compiler support for forcing you to stay out
           | of that quadrant, my code runs at high concurrency rates
           | precisely because I've learned how to stay out of there, and
           | my code looks very Erlang-ish when you look at the
           | concurrency patterns in play.
        
           | Chris_Newton wrote:
           | _new boss who once tried to write a 2-threaded app and got
           | burnt, so from then onward he mandated to never use multiple
           | threads_
           | 
           | An unfortunate overreaction, I agree.
           | 
           |  _Does everything have to become dumb to make it safe?_
           | 
           | I don't think trying to avoid shared mutable state is dumb.
           | It's deliberately choosing a safer default, just like not
           | allowing all references to be null or not accepting the
           | string "123" where an integer like 123 is needed.
           | 
           | Sometimes it can be useful to have shared mutable state, or
           | to make a reference nullable, or to accept different types of
           | data and quietly reinterpret them the same way internally.
           | But these are inherently more dangerous styles of programming
           | -- they create opportunities for mistakes that are otherwise
           | systematically prevented -- so it seems reasonable to
           | encourage the safer alternatives unless there is a good
           | reason not to use them, and to make the more dangerous
           | choices the ones you have to make explicitly.
        
           | kephasp wrote:
           | I'd ask the opposite question: why would you use a dangerous
           | paradigm when a safe one exists and the dangerous one doesn't
           | offer much benefit?
        
             | bitL wrote:
             | The question is if the "unsafe" one really doesn't offer
             | much benefit. If the unsafe one leads to a 3x speed up or a
             | 10x lower memory consumption, then I'll use it.
        
         | jahewson wrote:
         | > Functional programming is a reaction from the shift to the
         | dangerous quadrant of the immutable-mutable/unshared-shared
         | "Magic Quadrant" chart.
         | 
         | This makes it sound like you're saying that's why functional
         | programming was created, which isn't the case. I assume you
         | mean that this is why it's gained popularity but I don't really
         | agree with that - it's certainly valuable but most functional
         | programmers will never touch threads. I'd argue that programs
         | without state are just easier to reason about and debug and for
         | most software this is where the value comes from.
        
           | klipt wrote:
           | > I'd argue that programs without state are just easier to
           | reason about and debug
           | 
           | Right, isn't the fundamental trade-off between programmer
           | efficieny and runtime efficiency?
           | 
           | Immutable structures are easier to reason about, but almost
           | always run slower than their mutable counterparts.
           | 
           | The holy grail would be immutable structures that are equally
           | performant, but I'm not sure that's even mathematically
           | possible in general.
        
             | kephasp wrote:
             | Is there data supporting the notion that immutable
             | structures are slower?
             | 
             | There are many cases where there won't be a single
             | difference in performance and there are a bunch of cases
             | where immutable structures will be way faster than mutable
             | ones.
        
               | philipkglass wrote:
               | The most obvious case I'm aware of is with large
               | numerical simulations in scientific computing. I worked
               | on molecular simulations in graduate school. The core
               | data structures are large (many-gigabytes) arrays, and
               | almost every element of the array is updated on every
               | iteration. Everything that requires more memory or even
               | more memory accesses is going to be slower. In business
               | applications you're usually not updating everything in a
               | data structure all the time, so I can see how clever
               | immutability may improve performance.
        
             | philipkglass wrote:
             | It's not possible to do always but it feels like it should
             | be possible in special cases. If you can prove that a value
             | V2 is ultimately derived from a modification of V1, and V1
             | is never referenced after creating V2, then it should be
             | possible to invisibly convert this to an in-place mutation
             | [1]. In the case of applying a bunch of text normalization
             | rules to a string, for example, I care about the final
             | string but not the intermediate states. It could be
             | mutation underneath and I'd be none the wiser, except that
             | the runtime performance would be better.
             | 
             | In Scala you can add a "@tailrec" annotation to recursive
             | functions. The annotation means that the function is
             | guaranteed to recurse efficiently (without growing the
             | stack) OR that the compiler will give an error telling you
             | why it can't be guaranteed. I could imagine a similar
             | annotation like "@withmutation" for functions where you
             | want to guarantee efficient in-place mutation at runtime.
             | As it is, when I run into performance pain points in Scala
             | I redo the critical bits with (manually written) while-
             | loops and imperative mutation.
             | 
             | [1] Unless you later attach a debugger and expect to be
             | able to observe V1 and V2 simultaneously. But I presume
             | this sort of issue already comes up and is somehow dealt
             | with regarding other compiler optimizations.
        
               | cassepipe wrote:
               | I think this is the idea behind Richard Feldman's Roc
               | programming language https://www.roc-lang.org/
        
         | at_compile_time wrote:
         | What are the advantages of complete immutability when we can
         | write compilers that specifically prevent shared mutability?
         | You're avoiding the dangerous quadrant but also excluding a
         | valid one. I'd definitely prefer FP's solution over Python's
         | GIL, but it still feels like an unnecessary compromise.
        
           | assbuttbuttass wrote:
           | Most functional languages allow mutability when you need it,
           | they just default to immutable data. Haskell might be the
           | exception, where everything has to be immutable all the time
        
             | marcosdumay wrote:
             | Everything does not have to be immutable in Haskell. It's
             | only that mutability can only exist in IO or some other
             | context that deals with it. The language enforces purity,
             | not immutability.
        
             | poorlyknit wrote:
             | This is not true, Haskell of course allows you to mutate
             | state. It just forces you to declare it: For example,
             | there's a MutableByteArray type whose operations only work
             | in a specific Monad (because Haskell...) [1].
             | 
             | There's also more basic stuff like IORef which represents
             | an assignable variable [2]. Again, you're constrained to
             | use this in IO contexts.
             | 
             | Etc.
             | 
             | Haskell basically just forces you to do that thing someone
             | else in this thread mentioned: Write functional APIs, allow
             | side effects but make them explicit and confined to very
             | specific places.
             | 
             | [1]: https://hackage.haskell.org/package/primitive-0.7.4.0/
             | docs/s... [2]: https://hackage.haskell.org/package/base-4.1
             | 6.3.0/docs/Data-...
        
         | heavenlyblue wrote:
         | Functional programming is representing the program state as a
         | single expression, so that the compiler could do funky maths
         | stuff in reordering things in it. It has little to do with
         | immutability or functions per se.
        
         | DonaldPShimoda wrote:
         | Just a small nitpick about your comment:
         | 
         | > Functional programming is a reaction from the shift to the
         | dangerous quadrant of the immutable-mutable/unshared-shared
         | "Magic Quadrant" chart.
         | 
         | I might rather say " _The recent focus on adapting functional
         | programming_ is a reaction... ". Functional programming itself
         | is nearly as old as the modern computer (McCarthy's first LISP
         | paper was published in 1960), but your phrasing kind of
         | suggests that the entirety of FP is a recent innovation.
        
           | frostwarrior wrote:
           | Functional programming itself is really old. Practical
           | functional programming for scale is the new trend.
           | 
           | What's new is the scale of software being developed right
           | now. Developers simply can't afford to create mutable and
           | shared state as if their program was just another desktop
           | program, executed on a computer disconnected from the
           | internet.
           | 
           | Sooner or later we learn that focusing on the human value of
           | code (I mean, making the code clear, concise and simple to
           | read) pays off way better on the long run rather than
           | optimizing for CPU cycles or memory footprint.
        
       | tacone wrote:
       | Simply put: to have one more option.
        
       | nnoitra wrote:
       | So you can pretend to be smarter than you are solely based on the
       | paradigm.
        
       | clircle wrote:
       | As an R user, FP seems like the norm. Working with data or stats
       | without FP mechanics sounds unpleasant.
        
         | epgui wrote:
         | As another R user and FP aficionado, most R code is non-FP. If
         | you work somewhere where you need to use R, and FP patterns are
         | the norm, you're lucky!
        
       | dbrueck wrote:
       | In my mind, 'wustl.edu' will forever be one of best treasure
       | trove FTP sites back in the late 90's. That is all.
        
       | [deleted]
        
       | pharmakom wrote:
       | Even if you don't find it very interesting, functional
       | programming can make you rich.
        
         | nnoitra wrote:
         | How come, it's barely used in industry lol.
        
           | kephasp wrote:
           | It's not used by many, but it's used by niche environments
           | that have a lot of money, especially in Fintech. When you
           | want your code to be extremely reliable while really fast,
           | there's nothing like languages like OCaml or Haskell.
        
           | epgui wrote:
           | You don't become rich or great (and then maybe rich) by
           | following the biggest crowd, so I don't see how your response
           | is relevant.
        
           | pharmakom wrote:
           | Top paying languages are Clojure, F#, OCaml
        
       | jjice wrote:
       | It's the same reason to learn alternatives to anything: to have a
       | wider breadth of knowledge. Your thought process becomes more
       | open and can better way alternatives because you actually have
       | alternatives.
       | 
       | My compiler course in college was in SML and it was excellent for
       | teaching more more than just compilers. It taught me a lot about
       | recursion and the idea of composing a problem in terms of itself,
       | which has been incredibly powerful in my career.
       | 
       | Being exposed to other great concepts like algebraic data types
       | (sum types/Rust's enums) just helps expand my way of thinking
       | when I write PHP code at work.
       | 
       | The idea of using a function as a fundamental building block for
       | abstracting ideas has also been fantastic. Mostly in the form of
       | using functions as arguments to alter behavior.
       | 
       | As with everything, there's a balance. I don't write pure FP, nor
       | do I want to, but the ideas are huge. Same with OOP. OOP has some
       | good ideas, but I don't lean on the words of the GOF as if they
       | were GOD. Pulling in the best of all worlds has been really huge
       | for my life as an engineer.
        
         | Banana699 wrote:
         | Dijkstra once explained how his process for writing code is to
         | state\solve the problem in the most obvious and natural
         | language possible. If a compiler\interpreter existed for that
         | language, then he's done, he now has an executable solution to
         | the problem. If not, then he recursively solves the problem of
         | translating each construct of this non-executable-but-
         | convenient language down into other constructs, if _those_
         | constructs are executable, well and good, if not, he has to
         | break them down further.
         | 
         | Learning new programming languages, paradigms, architectures,
         | approaches and formalisms aids this process because it gives
         | you more mental building blocks to use in your journey from
         | non-executable specifications to executable implementations.
         | Even if you never write haskell, learning it makes your brain
         | evolve a haskell-like pseudocode in which to think and express
         | problems, and this can come in handy when the problem is most
         | naturally expressed in haskell. If a haskell implementation
         | exist, great, if not, transform the haskell formulation
         | gradually into whatever executable form available. This, for a
         | certain class of problems - let us rather unimaginatively call
         | them 'haskell problems' -, is better and more enlightening than
         | attempting to directly solve them in executable format.
         | 
         | ------
         | 
         | One common saying is "You Can Write Fortran In Any Language",
         | another one is "Any Sufficiently Complicated C Program Contains
         | An Ad-hoc Informal Implementation Of Common Lisp".
         | 
         | The fundamental truth that both of those aphorisms hint at is
         | that programmers are human compilers, the programming language
         | they write in is their target language, the "assembly", and the
         | description of of the problem they are solving is the source
         | language they are compiling. Here's the thing though : just
         | like actual compilers, programmers don't have to compile the
         | source language all in one go. Machine compilers often go
         | through several detours and meander through different
         | intermediate representation of the code being translated before
         | outputting the final target. The equivalent of this for
         | programmers is the Dijkstra process, describe your problems in
         | a hierarchy of languages that _ends_ , not begins, with the
         | programming language you happen to use.
         | 
         | If the problem is best described as a Fortran program, write it
         | (in your head) as a Fortran program then implement whatever
         | necessary of Fortran in the actual available language to write
         | the program. If the problem is best described as Common Lisp
         | program, then think about it in your head as a Common Lisp
         | program then implement the necessary parts of Common Lisp in C
         | to write the program (The full quote is only saying this is bad
         | insofar as it happens non-deliberately and haphazardly, if it's
         | deliberate then it's just good design). Programming Languages
         | are notations/pseudocode/ways of thought/mental models/semantic
         | repositories of meaning, they can be useful even if there is
         | not a single executable implementation of them in sight.
        
           | kazinator wrote:
           | > _If a compiler\interpreter existed for that language ..._
           | 
           | Then Dijkstra would have written a disparaging article about
           | it, and then worked the solution in Algol 60.
        
           | dial9-1 wrote:
           | every program is a compiler
        
       | orthecreedence wrote:
       | I've been taking a kind of middle ground lately: build functional
       | APIs. Move your side effects as far outward as possible and make
       | your library's interface take everything it needs and return
       | everything it computes. No HTTP calls, no database access, no
       | random number generation. For example, don't have your library
       | build the query and then run it, have it built the query and
       | return it so it can be run at a higher-level.
       | 
       | I know this seems obvious, but it was a breakthrough I had with
       | organizing the way I built things a few years back and it has
       | been serving me amazingly well. I think I originally stumbled
       | onto the idea through a talk on domain-driven development.
       | 
       | The result is that you get a lot of the benefits of functional
       | (easy testing, portability, etc) but you don't have to deal with
       | all the oddball patterns of recursion or currying or things that,
       | yeah, sure, makes sense on some theoretical level but makes me
       | want to gouge my eyes out when I try to read it. I've tried
       | fully-fledged functional programming in a few cases and it
       | doesn't click with me. I appreciate and understand that some love
       | it, but in the end if your exposed public API is functional, the
       | internals are less important.
       | 
       | To me the important thing is the mindset: move your side effects
       | as high up the chain as you can.
        
         | adamkl wrote:
         | The term for this that I have come across is "stratified
         | design" and goes back to the book Structure and Interpretation
         | of Computer Programs by Abelson and Sussman. I have no idea why
         | this approach isn't more well known (especially compared to
         | typical "layered" design approaches) as the benefits are so
         | great!
         | 
         | https://medium.com/clean-code-development/stratified-design-...
        
         | jmt_ wrote:
         | Is there a good open-source example of this paradigm? I'm
         | interested by the idea but struggling a bit to see how it would
         | actually be implemented for something like, say, a regular
         | REST/JSON API.
        
         | i_hate_pigeons wrote:
         | this is what I learned is functional programming and I've also
         | benefited greatly from it
        
         | mdcds wrote:
         | I tried learning Haskell for fun while working as a Python dev.
         | Understanding importance of managing side-effects definitely
         | influenced how I changed my approach to code organization at
         | work.
        
         | kephasp wrote:
         | You may find it interesting to study FP a bit more, because
         | recursion, when understood, is pretty universally felt as way
         | more readable than its imperative alternatives.
         | 
         | I also usually find currying extremely practical and easier for
         | me when it's available.
         | 
         | Most of us that only use FP in our day job don't do it out of
         | masochism, AFAICT. I certainly don't.
        
       | yodsanklai wrote:
       | Modern languages assimilate ideas from all paradigms. Besides, FP
       | isn't some theoretical obscure stuff. I'd except most programmers
       | to know some rudiment of Scheme or ML.
        
       | whitenickel08 wrote:
       | I miss Erlang-ish languages in the article.
        
       | 112233 wrote:
       | That lowly imperative programming: hard to prove your program is
       | correct. Functional programming: easy to prove your program is
       | correct, hard to prove its' execution will fit in the known
       | universe.
       | 
       | Functional programming IS math, so it's super satisfying to learn
       | intellectually. It is also a spherical cow.
        
         | kephasp wrote:
         | Why would it be hard to prove that functional code is actually
         | runnable?
        
       | rekrsiv wrote:
       | Because it allows you to compose anything from only functions and
       | category theory.
        
       | agentultra wrote:
       | Because there is an essential complexity to programming in
       | general that you cannot escape. Avoiding functional programming
       | is like navigating a dark cave by bumping into obstacles when you
       | have an assistive technology that can guide you.
        
       ___________________________________________________________________
       (page generated 2022-08-02 23:01 UTC)