29 ms·
FP vs. OO, from the trenches
- MatthewPhillips 13y agoFogus makes the same point in Functional JavaScript (I highly recommend it).
- mef 13y agoAnyone care to expand on the reasons for the guideline?
- mhaymo 13y agoWithout such reasoning, this article is kind of worthless, and I'm not sure how it got to the top of HN.
- RogerL 13y agoFunctional programming works great for processing data - you don't want to change the data, and there isn't a lot of state. You largely write various transforms and filters, which is right in FP's wheelhouse. On the other hand, simulation is quite state-full, often has tons of little details that you don't want to expose to the world (encapsulation), the thing that you are simulating usually has a collection of varying behaviors that you can represent via polymorphism or composition, they have attributes, and the 'engine' is often easier to write if you use dynamic(virtual methods)/static(generics)/duck polymorphism to get your things to do their, well, thing. Which is not to say that either is undoable or really hard in the other paradigm, but if I am simulating something I am often thinking of 'objects' and doing things to them; the OO paradigm helps you program about that in a very expressive way. Ditto for FP and functional programming - I'm thinking about filtering and transforming data. That is just my view of the author's article, with a caveat. I've seen terrible, beastly simulations done in OO that basically thought that single inheritance is how you spell OO. A single type hierarchy bites you so hard: 'Oh, I'm make everything a widget with draw/eat/process/whatever methods'. Then requirements change, and widgets in this subtree need to do something you thought only widget in that other subtree would do, next requirement has you needing to reflect on who can do what, and so on. You end up with a huge Blob object at the top of your hierarchy, or you endlessly end up with huge blocks of RTTI/reflection to figure out what kind of thing you are dealing with, or otherwise try to work around the problem that the world is not easily decomposed into a single hierarchy. In practice I find all of this terribly reductive. Need some small thing whose behavior varies in well defined ways? Use polymorphism. Have a bunch of stateful stuff that you need to keep track of? Encapsulation is nice. Want to perform some operation on a large collection of data? Look to transform(). Need to make a lot of inferences and conclusions? Perhaps logic programming will work there. Need to provide a framework where people can build larger systems? Hopefully you are using component or services based ideas. And so on. A programmer should have a bunch of tools handy, and use the best one for the job. On the other hand, just about every person I interview opines that we should inherit for re-use, and I silently despair.
- deleted 13y ago[deleted]
- bsg75 13y agoHaving seen some in the MS camp suggest that F# is a good candidate for data work (vs C#) for similar reasons, are there languages in the cross platform crop whose strengths lend towards data (string) processing (vs app development)? OCaml becomes interesting given the above due to syntax similarities. Scala/Clojure due to Java library support(?). Haskell because it seems to get a good amount of attention.
- kyzyl 13y agoF# is a pretty nice language, but you are indeed still in Microsoft land. That said, mono has gotten pretty good over the years. As far as data processing goes, I've seen both scala get some attention in the data game, because you can easily write hadoop jobs, and you can fairly easily interface with libraries like ATLAS for matrix work. However, working in a functional style in the JVM with lots of data can bite you sometimes, particularly with GC hiccups where the GC just wasn't designed to work efficiently with functional resources usage. Personally I think Haskell is very well suited to data work. You get pretty good speed out of the box, concurrency and parallelism are baked in, and the library support is pretty extensive. It's also quite cross platform. In addition to that, you've got brilliant folks like Simon Peyton-Jones working on stuff like automated stream fusion, which can mean huge speedups. To me the main disadvantage to using haskell for data processing is the relatively long compile times. Since "data science" is typically fairly interactive, until you are pretty good at haskell you might find yourself waiting a long time to realize you've done some silly things. It's really a situation where things liker IPython's html notebooks are invaluable. Sidenote: As far as string processing goes, I've found working with haskell's parsec library to be simply great for creating parser combinator libraries in a very natural way.
- chongli 13y agoHave a bunch of stateful stuff that you need to keep track of? Encapsulation is nice. I think this one is open for debate. There are other models for managing state which make things simpler to reason about than classical OO with encapsulation. One such example is Clojure's epochal time model. http://www.infoq.com/presentations/Value-Values http://www.infoq.com/presentations/Value-Values
- bluehex 13y agoThis post is nearly devoid of information. At least an example of what the author means by modeling data about people v.s. stimulating people might have helped. Most problems I encounter don't relate to people at all but maybe I'm to just replace 'people' with 'things'?
- city41 13y agoI'm puzzled why this is currently at the top of HN. I'm assuming the author must be someone well known who I've missed out on, as that seems to be the only way posts devoid of value push forward around here.
- dysoco 13y agoIndeed, he's a famous opensource developer and wrote some books, including "The Joy of Clojure" one of the most famous Clojure books out there.
- fogus 13y ago"Famous" is a huge stretch. Say my name to 1,000,000 Java programmers and you're likely to get 100% "huh?"
- cldr 13y agoSay anything to a Java programmer and you'll get a "huh?" so don't feel bad.
- pjmlp 13y agoNot fare to single out Java for the quality of the average enterprise developer. You will get a "huh?" from the majority of developers management likes to hire as cogs.
- michaelochurch 13y agohttp://www.youtube.com/watch?v=fHKrCs1rFRI#t=1m19 http://www.youtube.com/watch?v=fHKrCs1rFRI#t=1m19 Fogus: Say my name-- Declan: You're Heisenberg. Fogus: -- to 1,000,000 Java programmers and-- Declan: WTF? -- On a more serious note, the above is my way of giving props because Joy of Clojure is a really good book.
- Mordor 13y agoLong story short: the next big thing is a language which mixes both FP and OO.
- ams6110 13y agoThat would be most languages in wide use today.
- ihsw 13y agoPersonally the only point of contention with FP vs OOP is immutability, or more directly managing state. The distinction between 'simulating people behavior' and 'measuring people behavior' is probably intentionally vague to spur the imagination, but it's quite apt. Many languages implement multiple flexible looping/filtering structures to discourage shoving everything into for/while loops (which are susceptible to confusing and messy continue, break, goto, yield statements strewn about). Furthermore the rationale behind Clojure[1] is stateful objects are a new kind of spaghetti code, and managing state across scopes requires breaking mental boundaries. [1] http://clojure.org/rationale http://clojure.org/rationale
- bascule 13y agoI think the larger problem is referential transparency: most OO languages allow two objects that represent the same states to have distinct identities, even if compare-by-value claims they're equal. Of course, it's not impossible to have referentially transparent objects. I wrote such a language (Reia)
- fogus 13y agoThis kind-of hearkens back to simulation I think. That is, if two objects have the same properties then it might be useful to identify them as distinct things because they are in fact distinct entities. That they happen to have the same properties is a matter of fidelity only.
- groovy2shoes 13y ago
- huherto 13y agoI don't think you have to choose one or the other. They are not mutually exclusive. Furthermore, I still use Structured programming ideas along with OOP and FP.
- alipang 13y agoKinda weak post, though what he said in point four vibes with me, where he argues for using OO on the lower level with a functional API / abstraction. This is a really underutilized design strategy. Much too often architecture is discussed in OO vernacular, and as a result is made much too complicated. I think we'll come to see OO as a low-level technique more and more.
- ajanuary 13y agoGary Bernhardt has a screencast [1] on DAS that proposes the opposite architecture of functional core, imperative shell. [1] https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell https://www.destroyallsoftware.com/screencasts/catalog/funct...
- waxjar 13y agoFour footnotes on a two paragraph article? Guidelines seem sensible though.
- reeses 13y agoThink of it as four powerpoint slides with one "source" each.
- reader5000 13y agoIf you're doing something like agent based modeling, FP is great since you get snapshots of your simulation "for free". And whats the difference between e.g. agents[0].location.x += 5; versus (update-in agents [0 location x] + 5)
- williamcotton 13y agoIf you have a simulation, where the outcome is not known and individual Objects are keeping track of their own data and behavior... VS. ...you already have data about a set of things and those things aren't going to be changing their own data. Think, Video Game VS. Data Visualization
- williamcotton 13y agoIf I have a run loop/game loop, I always use OOP. I'm curious, has anyone ever implemented a run loop in a functional style? I know there are recursive approaches to passing the time deltas and what not, but it seems rather difficult to make video games with a purely functional approach... Can anyone offer any insight?
- augustl 13y agoOne insight is that functional programming and pure functional programming are very different beasts. As an example, Clojure does not aim to be pure, Haskell does. In Clojure, the focus is on immutability, and state is modeled as a succession of immutable values. Example: the employees in a company is represented as an immutable value. A place (a ref) stores the current immutable value, and you can always ask this ref for that value, and set it to a new one. But the value itself is always immutable. In Haskell, everything must be pure, and uses monads to models things such as random number generators, I/O, and other side effects.
- klibertp 13y agoIt is hard. At least that's what I read in: http://prog21.dadgum.com/23.html http://prog21.dadgum.com/23.html EDIT: but not that hard, according to http://prog21.dadgum.com/37.html http://prog21.dadgum.com/37.html ;)
- williamcotton 13y agoWow, thanks for that link! The author's explanation was incredibly clear and I feel like I got a handle on it! Just 'lift' the relevant game state and pass mutatations along in a simular way to how you might pass exceptions along with a promise based system... Then it eventually feeds to a makeSounds() or an updateAnimations() or whatever! That way the code can keep all related functionality in one place, instead of spreading sound or animation related methods all over the code base encapsulated in each object with its own logic! Brilliant!
- lispm 13y agoI would propose the opposite.
- btilly 13y agoI have a version of this that I've used for years. Objects make good nouns. Closures make good verbs. Software organized around nouns looks different than software organized around verbs. Not better. Not worse. Different. Use what is appropriate.
- deleted 13y ago[deleted]
- guelo 13y agoA concept from a classic Steve Yegge rant, http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom...
- btilly 13y agoHe said it better, but I said it before he did: http://www.perlmonks.org/?node_id=318563 http://www.perlmonks.org/?node_id=318563. The root of that discussion was http://www.perlmonks.org/?node_id=318257 http://www.perlmonks.org/?node_id=318257 which I think is interesting in its own right.
- dustingetz 13y ago"Objects make good nouns" most 'objects' as they exist in today's OOP have methods, which makes them both nouns and verbs. Idiomatic code in most of today's mainstream OO languages doesn't make heavy use of closures, mostly only Javascript. Anyway, the closures vs methods debate has been going on for decades is not a closed topic[1], and the answer certainly depends on the language you're using. [1] http://www.c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent http://www.c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent
- samatman 13y agoI don't believe this is a nitpick, but fully encapsulated OO provides only nouns and verb phrases that have a pre-specified noun. This is different from data structures (nouns) with collections of functions (verbs) that can act on many data structures in a consistent way.
- abecedarius 13y agoThe lambda calculus was the first object-oriented language. http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf explains this and proposes a crisp distinction between OOP and abstract data types.
- davidcuddeback 13y agoI read that paper a couple years ago and it changed the way I see object-oriented programming. All of a sudden, the dependency inversion principle just clicked. I hope I hit the upvote button instead of the downvote button. I'm typing this on a shaky train and my browser will only zoom in so far.
- doorhammer 13y agoYou know what has a lot less information than the blog entry? All the comments about how little information it has. Well... and this post, now. I always come to the comments to throw a little balance or extrapolation into my reading, and its disappointing to find people mostly just complaining. Got a few interesting nuggets, though. So not all bad.
- the1 13y agois facebook.com about people or simulating people?
- jb55 13y agoI've always viewed OO as a nice optional UI for most programmers. Given an object to mutate and call methods on seems to click for most people. I tend to go for a more functional style internally for the composibility and maintainability properties you gain.
- babarock 13y agoI'm a bit confused. I always thought that FP and OO were orthogonal concepts and never considered them mutually exclusive. To me, the antitheses of FP would be imperative programming. Maybe I'm missing something? CLOS, OCaml, Scala, I can think of many examples of languages that include components of both FP and OO. Or maybe we're simply considering that OO means this special paradigm used in C++/C#/Java (that really only claims to be the true and only OOP by the commercial entities backing these languages)? PS: I googled around a bit, this Clojure article [1] seems relevant. [1]: http://clojure.org/state http://clojure.org/state
- fogus 13y ago> never considered them mutually exclusive. I never implied mutual exclusion.
- pr0filer__ 13y agoI'de say versus implies mutual exclusion
- cygx 13y agoActually, FP and OO are mutually exclusive to some degree: OO comes from the imperative end of the spectrum (after all, objects are an abstraction over mutable state), whereas FP comes from the declarative end (a pure function is a relation between sets and mutability is a foreign concept). However, most programming languages are impure and support both paradigms, so you can get away with thinking about OO and FP as orthogonal ways to reason about and structure your code; language syntax and semantics may of course favour one concept over the other...
- bad_user 13y agoOOP is not about hiding / dealing with mutable state, although it can be used that way, but that's a perverted idea of what OOP is. OOP is about subtype polymorphism [1] by means of runtime single-dispatch [2] and modularity, as in abstract modules or components that help with decoupling, a notion supported explicitly by SML, or exemplified beautifully in the Cake-pattern used in Scala. [1] https://en.wikipedia.org/wiki/Subtyping https://en.wikipedia.org/wiki/Subtyping [2] https://en.wikipedia.org/wiki/Single_dispatch https://en.wikipedia.org/wiki/Single_dispatch
- eternalban 13y agoFP makes an excellent backend -- architecturally speaking -- for OO-, REST-, front-ends, and a most excellent front-end for Relational systems. (Haskell, for example, would be a dream language for sprocs.)
- gruseom 13y agoI find this post suggestive. The title—"from the trenches"—makes the important point that this is a reflection from experience on what seems to work best where. That's more valuable and harder to come up with than it sounds, because if you identify with a paradigm then you don't easily notice it getting in your way. I would like to hear a more detailed treatment of the distinction between "dealing with data about people" and "simulating people". If these overlap (and surely they do), then you get into a circularity where your favorite paradigm leads you to see a problem its way, just as much or more than the problem nudges you toward a paradigm for solving it. On the other hand, my experience matches the OP's that OO's sweet spot is close to its origins in simulation--where you have a working system that exists outside your program, your job is to model it, and--critically--you can answer questions about how it works empirically. When you aren't simulating anything, OO is cumbersome because it requires you to name and reify concepts that become "things" in your mind; these ersatz "things" continually draw attention to themselves and get between you and the problem.
- pdog 13y agoFor actor-based programming in Clojure (complete with real lightweight processes, selective receive and an Erlang-like API), look no further than Pulsar: http://puniverse.github.io/pulsar/ http://puniverse.github.io/pulsar/
- jacquesm 13y agoFor all those hating on this blog post: It's short, but it doesn't have to be long to be useful, and apparently it is useful given a substantial chunk of the comments here. If it wasn't news to you then ignore it, otherwise appreciate that not everybody is quite as enlightened as you are. HN has a tremendous reach these days, from pioneers in the field to total (and often clueless) newbies. Fogus felt compelled to write down his thoughts, someone else saw fit to post it and as of this moment 100+ people thought it was useful enough to vote it up. If that's not validation enough for you then remember that time when you spent half a day tracking down an endless loop and you had to ask a more seasoned programmer to point it out to you. Fogus is a respected member of the community because he tends to write down what he thinks in a way that others much further down on the totem pole can grasp it too, his articles are not upvoted because he's 'well known' but mostly because people find them useful. If you feel like this article was 'devoid of content' or whatever slur you feel like directing at it then please, write a better one.
- semiprivate 13y agoThat's not a real argument. You're essentially saying "respect because I said so." The irony is your argument is just as flimsy and opinionated as everyone else's. This article is devoid of content AND is written by a respected member of the community but neither of those things make it worth reading. The great moral of the story here is, if you let the internet bother you, the internet will definitely bother you.
- jacquesm 13y agoContent is not determined by the quantity of words on a page. Some of the deeper links between linguistics and programming can be quite eye opening and it does not require a large number of words to put those down. If you find one of these, especially through your own work (as in 'from the trenches') then that should carry some weight with you. If you're doing this independently and re-discovering something that apparently a lot of people such as you have already found out or learned about elsewhere then indeed it is devoid of content. But I'll bet that it wasn't the case for the majority of those that read it. Lots of programming wisdom is so terse that we have acronyms for it (DRY for instance), that does not mean there is no content there. Anyway, enough said, I think it is worth reading, and worth 'grokking' for want of a better word, in case you had not already discovered this. Naming stuff is one of the harder things in programming, that different streams of programming should lead to different groups of words being used to describe the code should probably come as no surprise and yet I find myself amazed that there are such deep connections.
- dakimov 13y agoThis is one of the most stupid assertions related to programming I've ever read.
- michaelochurch 13y agoOne thing that bugs me in the imperative vs. functional debate is that we (functional programmers) often show people a side-by-side comparison with 20 lines of imperative code, 6 lines of functional code, and say, see, the functional code is so much better! Well, to us, it is. Filtered through our biases, it's much more intuitive. I think we're wrong on one thing. Personally, I think imperative code is more intuitive. It matches how people think of operational behaviors. For a 20-line program that will never grow, I'd rather see an imperative straight-line solution. FP wins when things get a lot more complex: various special cases and loops within loops. Stateful things compose poorly. Debugging a 300-line inner for-loop is no fun. Functional programming, done right, means people factor long before it gets to that point. Factories and Visitors prove what hellishness comes into being when one doesn't have those functional primitives, but this does not make the superiority of FP intuitive or obvious. Now, OO is so variable in definition that it's very hard to know exactly what people mean. There's the good OOP (Alan Kay's vision; encapsulate complexity) and then there's bad OOP (overuse of inheritance, auto-generated classes, Factories and Visitors). One can conceive of core.async as an OOP win in Clojure; lots of complexity (macroexpand a go block at some point) is being abstracted behind the simpler interface of a channel.
- chris-martin 13y ago> Personally, I think imperative code is more intuitive. It matches how people think of operational behaviors. The masses agree with you, apparently. That's why they sit in their cubes all day writing the same god damn re-implementation of map over and over again List<String> result = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { result.add(input.get(i).toString()); } instead of input.map(_.toString) because functional programming is confusing.
- pjmlp 13y agoQuite true. I still don't understand why recursion is confusing to learn, as for me it was obvious from day one. Then again I am good at maths. Additionally, I had lots of fun doing Caml and Prolog when I was at the university. So even though I tend to do the typical boring enterprise JVM/.NET/C++ stuff, I do welcome the FP contamination of those ecosystems. :) However on my last project, I had to rewrite some LINQ stuff back to plain imperative code, because few people on the team could manage it (LINQ). :(