
What's wrong with Object-Oriented Programming and Functional Programming - roguelynn
https://yinwang0.wordpress.com/2013/11/09/oop-fp/
======
monjaro
This is a low quality article from someone who, given his qualifications,
should know better.

The criticisms of functional programming languages range from trivially true
(you can't be purely functional and have side effects) to incorrect (it is
certainly not difficult to create a circular data structure in Haskell - it's
easy given laziness).

The criticism of OOP is verging on nonsensical. Of course functions can be
objects. A general definition of an object (following Cook somewhat) is
something that satisfies an interface along with some form of dynamic
dispatch. There is no reason why a function can't fall under that definition.
The distinction between “fundamental” and “derived” isn't a technical
argument, it's pseudo-philosophical junk. As several others have pointed out,
the fact that Java doesn't have proper first-class functions is also utterly
irrelevant. In fact, it is possible to program in a very pure OOP manner in
any language with proper closures.

If the author is representative of the quality of researchers working on
programming languages, it's no wonder the field seems stagnant.

~~~
fzltrp
> This is a low quality article from someone who, given his qualifications,
> should know better.

It really depends which audience this article is targetting (Do you believe
that S. Peyton Jones speaks in monads to his mother?). If this article was
written in response of a talk between undergraduates in a TA session, it is
perfectly acceptable, and even provides links to advanced material for the
curious.

> A general definition of an object (following Cook somewhat) is something
> that satisfies an interface along with some form of dynamic dispatch. There
> is no reason why a function can't fall under that definition.

Yes, but why have that definition, if you already have functions as builtin
types? Conversely, if there's a need for functions as builtin types, why force
programmers in using that clunky alternative? That's pretty much the point
made by the article: don't corner yourself in one paradigm when others might
be better at some tasks.

> As several others have pointed out, the fact that Java doesn't have proper
> first-class functions is also utterly irrelevant. In fact, it is possible to
> program in a very pure OOP manner in any language with proper closures.

Careful, the wording is a bit lacking here imho: you join two different ideas
and make it seem like the second one validates the first, while it's not the
case.

> If the author is representative of the quality of researchers working on
> programming languages, it's no wonder the field seems stagnant.

That shows you probably don't follow much the field. Anyway, this article
doesn't fit your standard (see first point), ergo this man's whole work
doesn't, ergo the whole field doesn't? That twice too much stretching from
someone who isn't very careful in his own argumentation.

~~~
monjaro
> It really depends which audience this article is targetting...

I disagree. Low quality articles like this are part of the reason why many
undergrads are full of strongly held opinions about things they don't know
much about. They think you can dismiss a huge paradigm with a glib one-liner:
"functions are not objects".

> Yes, but why have that definition, if you already have functions as builtin
> types?

Because we can't talk about objects without having a definition of what they
are? I have no idea what point you're trying to make here. I'm just trying to
be clear about my terminology.

> Careful, the wording is a bit lacking here imho: you join two different
> ideas and make it seem like the second one validates the first, while it's
> not the case.

Think about it a little bit and you'll see why they are actually very related.
His statement about Java is meant to imply that proper higher order functions
and OOP are in opposition in some way (at least I assume that's his point,
it's still not clear to me because that is obviously incorrect). I am saying
that proper higher order functions alone are enough for a very pure form of
OOP, so there is clearly no opposition.

> That shows you probably don't follow much the field. Anyway, this article
> doesn't fit your standard (see first point), ergo this man's whole work
> doesn't, ergo the whole field doesn't? That twice too much stretching from
> someone who isn't very careful in his own argumentation.

I'm going to ignore the digs at me and elaborate on what I meant. The author
wrote an article about programming languages that was full of elementary
errors, both in logic and in technical details. If he can't make a simple
argument correctly, how am I supposed to have faith that his research isn't
similarly full of errors? It's easy to disguise sloppy thinking in technical
writing.

~~~
fzltrp
> I disagree. Low quality articles like this are part of the reason why many
> undergrads are full of strongly held opinions about things they don't know
> much about.

I doesn't happen with undergrads only (but that doesn't make the whole
profession guilty of it all the time).

> They think you can dismiss a huge paradigm with a glib one-liner: "functions
> are not objects".

I don't think the article dismisses any paradigm whatsoever. It dismisses the
entrenchment in one paradigm at the expense of any other. That's the main
point. The explanation given is perhaps a little bit careless, I can concede
it.

> Think about it a little bit and you'll see why they are actually very
> related.

Relation does not imply causation, which I perceived in your wording, but I
might have been mistaken. Was I?

> His statement about Java is meant to imply that proper higher order
> functions and OOP are in opposition in some way

I don't think he meant that, but rather that the way Java never included
functions as "primitive types" was a mistake because of that need of OO
purity. The Runnable interface (or any interface containing a single method)
is an example of that problem (there are other reasons which may support the
existence of that interface though).

> I am saying that proper higher order functions alone are enough for a very
> pure form of OOP, so there is clearly no opposition.

That's debatable. I totally agree with you on the idea that FP let you
implement OO. Likewise, OO let you implement closures easily (there's a
duality there obviously, as in algebra vs coalgebra). However, I think that
OOP (or FP) as a full fledged paradigm included in any language - and not just
a library built on top of closures (or closures on top of objects) - makes a
lot of sense: it let the language incorporate syntactic sugar for all the
specific constructs related to OO, and it also enable the compiler to perform
better code analysis (though I suspect that it should be possible with a
library based implementation, but that would imply either the compiler to know
about it, or it having a very flexible - plugin like - mechanism to include
enhancements as libraries as well). I don't think that the latest evolution in
Java to include FP is a coincidence. Many languages have already been mixing
these paradigms with good success.

> I'm going to ignore the digs at me [...]

Good. Let's get that out of the way. I'm glad we're having a saner discussion.

> If he can't make a simple argument correctly, how am I supposed to have
> faith that his research isn't similarly full of errors?

I understand your point better now. Initially, I was very afraid you'd be
having the very same issue.

------
Ingon
This looks like an attack to functional programming mainly. And if you follow
Haskell closely I think that the guys building it are well aware that the
world is actually full of side effects. But the thing is that if they push the
"pure" ideology to its limits they will uncover a number of useful things
along the way. And that is the whole reason to stick to it. Maybe you don't
find the usefulness of monads, but that doesn't mean that there is no value of
composing part of you programs in this way. Otherwise you are stuck to the
same old ways of doing things.

So going with pure has its benefits for all of us, but this does not mean that
we should stick with something just because. Unfortunately the answer to most
of the questions in programming/software development is: it depends.

~~~
vimes656
> But the thing is that if they push the "pure" ideology to its limits they
> will uncover a number of useful things along the way.

For example new elegant approaches to parallelism/concurrency that would be
very difficult in an impure language.

~~~
danieldk
Indeed. For instance, something like

[http://hackage.haskell.org/package/parallel-3.1.0.1/docs/Con...](http://hackage.haskell.org/package/parallel-3.1.0.1/docs/Control-
Parallel-Strategies.html)

Would be very difficult to implement in a language that is not referentially
transparent and lazy.

------
jballanc
From a mathematical/theoretical point of view, this is an interesting article,
but I think it misses the larger point of programming language paradigms. Yes,
the PL researchers have their reasons for creating languages that are object
oriented, functional, procedural, imperative, declarative, logical, etc. but
those are rarely, if ever, the reason that _programmers_ choose these
languages.

Ultimately, the _main_ purpose of a programming language is to convey intent
to _other programmers_. If calling an object a function just because it has a
`__call__` method makes it easier to convey intent, then it doesn't really
matter that the object is not _really_ a function. Personally, I'd be
interested in any research into the ability to convey intent using these
different paradigms.

~~~
rybosome
In the case of natural language, I would agree with a statement similarly
worded to yours above, "The main purpose of a ... language is to convey intent
to other(s)". (Sorry for butchering, I promise I'm getting to a point =) )

I'm not sure I'd agree with respect to programming languages, however. These
are artificial languages designed to convey a limited set of ideas, with
varying degrees of abstractions over various concepts in electrical
engineering and mathematics. Given this, the purpose of a programming language
isn't just to communicate with others, it's also to shape how you approach
problems.

Anecdotally, learning the strict functional programming paradigm is what
allowed me to pass an extremely difficult technical interview recently. The
emphasis on dataflow and "do what I mean, not what I say" truly changed how I
thought and approached problems. Previously, my years of experience in
imperative languages lead me down a road that was a bit too missing-the-
forest-for-the-trees when it came time to solve a difficult, interview-style
algorithmic question.

------
eonil
The author should mention Smalltalk to talk about _pure OOP_. Not mentioning
Smalltalk means the author didn't really _researched_ the _pure OOP_. The
author just tasted some OO style languages. I really don't understand how can
the author argue about drawbacks of pure OOP with Python (which is more like
procedural) or Scalar (which is more like functional).

Also in the middle of text, the author frequently mention _most OO langauges_
which is nothing related to topic - extreme, pure OO language.

Mention about Haskell is pretty agreeable, but that drawback is already
published on Haskell website, and that's why Haskell support impure
operations.

I don't understand how can a Ph.D person can write this poor text.

------
tikhonj
This is a gross mischaracterization of functional programming and basically
attacks a straw man--one that's lamentably common when talking about
functional programming.

I'm going to repost a comment I wrote on the blog. It's long and really needs
editing, but I hope it gets my thoughts across. I think the part about OOP is
also misguided, but it's so obviously tacked on to a rant about functional
programming that I just ignored it.

Haskell’s “purity” is not about getting rid of side-effects but about
_controlling_ side-effects. It’s making side-effects _first-class citizens_ :
now you can write code that talks about having or not having them!

You can still have side-effects however you want, you just have to be explicit
about it. To some extent, the fact that this uses monads is incidental: all
that’s important is that there is _some_ IO type, _some_ ST type and so on–the
fact that they all form monads is almost an implementation detail. That’s why
some of the most exciting Haskell features–STM, the IO manager and so on–are
all about effects. Clearly, Haskell more than acknowledges effects, so the
entire diatribe about ignoring the existence of side-effects is attacking a
straw man.

Besides, you can’t simply replace a first-class system for managing effects
with static analysis, without essentially reproducing the same restrictions.
How would you do something like Haskell’s deterministic parallelism model or
reliable STM or the very aggressive loop fusion (and general rewriting)
Haskell uses? There’s a reason you don’t see these things done nearly as well
in any other languages: all of these fall apart as soon as you introduce side-
effects, so you need some way to help the programmer ensure things like this
are only used safely.

And this is exactly how types like IO and ST help make code safer. Sure,
_within_ an ST block, you have stateful code that’s just as hard to analyze.
But you can guarantee that this does not leak outside the block. Similarly,
functions can rely on their inputs not doing anything untoward however they’re
used. This allows you to explicitly state the assumptions about your inputs:
how is this a bad thing? In turn, this makes writing code that takes advantage
of these properties much easier: you can ask that your inputs do not cause
side-effects in a way that’s self-documenting and easy to verify. Then you’re
free to re-evaluate your inputs or call functions however many times you want,
as concurrently as you want. At the extreme, this can even be used for
security purposes: see Safe Haskell.

Sure you can write pure functions in any language. And you can write side-
effecting procedures in Haskell too. But the difference is that Haskell lets
you be explicit about whether you want side-effects or not–it’s just another
part of your interface. And this is how types like IO and ST help make your
code easier to think about: any code that is _not_ in a type like IO or ST can
only depend on its arguments, making all the dependencies more explicit.
(Note, again, how this is all independent of “monads”–it’s all about effects,
and the types just happen to form monads.) This does not make static analysis
too much easier, but that was never the point–the goal is to make the code
easier to think about, and knowing that there are no hidden state dependencies
certainly does that. A static analyzer can follow data flow easily, but it
requires quite a bit of thinking for the programmer to do the same!

The core motivation for managing effects à la Haskell is not “mathematical
purity”: it’s software engineering. We want code that is easier to think
about, has better guarantees and is more modular. The goal is to make code
less complex by removing hidden dependencies between distant parts of your
program (mutable state) and the effect of evaluation on the meaning of your
program (side-effects in general). You can refactor and move around most
Haskell code without worrying about breaking its surroundings because any
dependencies are explicit. You can extract something into a function,
consolidate multiple function calls into one or split one into multiple and
generally change your code up quite a bit without worry–these actions cannot
change the code’s correctness because effects are managed for you.

Ultimately, functional programming like Haskell is not just normal programming
with side-effects outlawed. Instead, it’s a different _basis_ for programming
which allows you to manage side-effects explicitly. In this light, papers like
“solved problem but with monads” are entirely reasonable: they’re about
bringing things over to this new basis. And this goes the other way too:
there’s a reason why you don’t see good STM, deterministic parallelism, stream
fusion (and rewrite-rule optimizations in general), anything like DPH and
anything like Safe Haskell in other languages.

~~~
pron
The way Haskell manages side effects is inspired, and I don't think anyone can
say that Haskell is not a beautiful and coherent language. I only dabbled in
Haskell a bit so I may be wrong, but I think that the problem with the way it
manages side effects is that it does so through lazy evaluation, and lazy
evaluation is hard to wrap your head around.

So I think that if there is one big problem with Haskell, it is this: you say
Haskell is about "software engineering". Indeed, the guarantees it provides
may assist with software engineering, but those guarantees aren't free. They
require programmers to think and program solely within Haskell's lambda
calculus and lazy evaluation framework, which is neither the way people think
nor the way computers do (the latter is important when doing performance
analysis on your code). This constrained framework also takes its toll on
software engineering, then. The question is, therefore, when are the
guarantees provided by Haskell worth their price? I think there are cases
where they certainly are, and cases where they certainly aren't.

(A tangential point: when thinking about software engineering, there are vital
issues that have little to do with the choice of the language. For example, a
language would have to be truly magical for me to forsake the JVM's vast
ecosystem, runtime linking, and runtime profiling and monitoring capabilities
– that's why I won't use GHC in my projects, but may certainly give Frege a
try)

~~~
jeremyjh
Dabbling really is not enough to show you the problems with your assumptions.
You are right that there is a cost, but it is really paid once up-front by
each programmer.

I could have written this same comment five months ago, before I started down
the long dark tunnel of doom which is to go beyond LYAH and trying to write a
real application. I think it was two months before I saw a light at the end of
that tunnel - and only recently that I have really begun to feel as productive
in Haskell as I previously was in Ruby. At this point, the costs you speak of
are paid up and I do not incur them when I write new code. Yes the type system
does impose a lot of structure and some boilerplate, but the benefits are
profound. Its the sort of statement I did not really fully credit before
experiencing myself, but I will say that is profoundly amazing how frequently
my code works perfectly once it compiles. This is particularly true when
refactoring. I remember sometimes in Ruby despairing to refactor some code
because I didn't want to fix all the tests...in Haskell once my tests are
compiling they are passing, and the compiler errors are usually very easy to
understand and fix (after several months of head-banging frustration).

~~~
pron
I don't doubt you, but your experience also provides little evidence. Have you
done profiling and performance analysis yet? Have you tried working in a large
team on a large project?

Different languages have different strengths. Some excel at quick and dirty
prototyping or small projects/small teams. Others make a 50+ developer team
more manageable. Some have good runtime performance, some have a shorter
development time, while others have better runtime monitoring and maintenance
tools. No language excels in all of these.

~~~
jeremyjh
Certainly my experience is insufficient. I have only dabbled in profiling and
performance analysis - enough to prove it can be done but that it can be time-
consuming and that sometimes you may have to give up some elegance/purity in
favor of performance. However the performance I get from naive code is so good
(so far) that I have not yet actually had to delve into it.

I am dubious of Haskell's prospects in large teams but I was completely
dubious of Haskell in general (like you) before I had experience in it.
Perhaps after experience with large teams I would be more bullish on this
point but I haven't had that experience so far. I am quite optimistic about
the size of the problem space that a small, skilled team (say 5 developers)
could solve with Haskell.

------
Tehnix

        Have you noticed how easy it is to implement circular 
        data structures or random number generators in C? 
        The same is not true for Haskell.
    

I might be wrong, but, isn't this a circular data structure (or, what they are
referring to)
[http://www.haskell.org/haskellwiki/Tying_the_Knot](http://www.haskell.org/haskellwiki/Tying_the_Knot)
?

    
    
        In a language like Haskell, where Lists are defined 
        as Nil | Cons a (List a), creating data structures 
        like cyclic or doubly linked lists seems impossible.
        However, this is not the case: laziness allows for 
        such definitions, and the procedure of doing so is 
        called tying the knot.

~~~
quchen
Yes.

    
    
      oneTwo = 1 : 2 : oneTwo
    

is a circular singly-linked list containing 1 and 2. If you wanted to change
the 1 to a 4 though, you would not be able to do so without creating an entire
new list. You can use Vector or Array (i.e. fixed-size containers) to make
yourself a circular buffer, but the implementation will be very similar to
what you would do in C.

~~~
cbsmith
Wow. That looks hard. I bet you stayed up all night working on that. ;-)

Seriously: sometimes things are hard because you don't know the language all
that well. Consider that possibility.

~~~
cbsmith
Just to be clear: the advice of "consider that possibility" is intended for
the author of the article. quchen clearly knows the "easy" way to do this kind
of thing with Haskell.

------
LukeHoersten
The author states the "extreme" case of OOP is "everything is an object" and
the extreme case of FP is "purity."

The problem with this analogy is that everything being an object doesn't by
you much. But in Haskell, the type system helps you keep track of what's pure
and what's not. So having a type system that keeps track of purity buys you
something: lots of pure and extremely easy to reason about code. Non-
deterministic (unpure) code is the same difficulty to reason about in any
language. Isolating it from pure code just reduces the amount of code which is
difficult to reason about.

------
j2kun
It looks like the author prides himself on reinventing ideas. I've read a
handful of his other posts, and he's "reinvented" the Y combinator, the proof
of the halting problem, and other such things. It appears that, perhaps
partially by a perpetual mishap with diction and connotation, the author
claims that his reinventions are original ideas, his opinions are fact, or
that his insights are somehow deeper or his arguments are better.

I see this happen all the time, with myself and with others, and I think it's
a common thing in mathematics (the author is in CS, so he might not get
exposed to this as much as I do). I've seen undergrads finally realize that
calculus makes sense and explain how much deeper their understanding is now
that they've really thought about it, and I smile and nod my head. I've myself
touted my own deep understanding like it's not completely trivial to somebody
with years of experience.

I think this article shares that sentiment. The author has thought of on his
own accord what we all consider a dead and beaten horse, and is shouting his
thoughts from his proverbial mountaintop: no paradigm is perfect for every
situation.

Best of luck to him for all his thoughts, but he'd better learn when and where
to curb his enthusiasm if he wants others to take him seriously. For the
record, this doesn't apply to his personal blog. I expect sooner or later
he'll have a post talking about how Haskell's pure style is all about giving
the sculpter more clay.

------
011011100
So does the author deny the existence of any sort of domain where these
paradigms would be "right"? Or are they universally "wrong"? Also, he states a
view or philosophy: "everything is an object" and then he says "this is wrong
because I disagree. functions are not objects". Wow. If you remove the
commentary about scala and python, which is irrelevant to his philosophical
thesis, then what is his argument? And why is it not a matter of just having a
different definition?

------
weland
This article is remarkably _low on arguments_ , despite being so long. Just a
few of its gems:

> OOP is wrong because of its definition of an “object”, and its attempt of
> trying to fit everything into it. When that goes to the extreme, you arrive
> at the notion “everything is an object“. But this notion is wrong, because:
> > There exists things that are not objects. Functions are not objects.

This has two problems:

1\. It's factually wrong. Smalltalk functions are first-class objects.

2\. It fails to explain _why_ that would be wrong (assuming it were, you know,
true).

The author does give the (poor) examples of Python and Scala, which -- in his
opinion -- incorrectly call a function an object, because only the __call__
and apply are the "function objects" one is trying to define, but they were
"kidnapped" and jailed into their wrapping objects. IMO, this is ontologically
incorrect. The same can be said of any object's definition: if I have an
object called PlaneVector, the "vector object" itself would actually be only
its x and y properties, which I have kidnapped and jailed into my object.

The fact that this structure (the object I'm defining in my programming
language) is _not the same_ as its counterpart in the world of ideas (i.e. the
plane vector in maths) should be fairly obvious, despite using the same
generic term (i.e. object) to denote both.

Behold, then, the straw man:

> Most OO languages also lack correct implementations of first-class
> functions. An extreme is Java, which doesn’t allow functions to be passed as
> data at all. You can always wrap functions into objects and call them
> “methods”, but as I said, that’s kidnapping. The lack of first-class
> functions is the major reason why there are so many “design patterns” in
> Java. Once you have first-class functions, you will need almost none of the
> design patterns.

There are a lot of things wrong with Java, of course, which does not mean that
they are also issue of object-oriented programming. Inheritance (sorry...)
doesn't work both ways: the fact that a Lexus is prohibitively expensive
doesn't mean moving vehicles are prohibitively expensive.

I have less of a problem with the author's treatment of functional
programming. What he's essentially trying to argue is that:

> Simulating them [side effects] with pure functions is doomed to be
> inefficient, complicated and even ugly. Have you noticed how easy it is to
> implement circular data structures or random number generators in C? The
> same is not true for Haskell.

IMO, this is true, but the isolation of side effects doesn't have to happen
only by the ugly means he outlines next (i.e. monads) in _every_ application.
A typical CRUD application the web kids like to write can be written so that
the only side effects involved are in fact modifications of the database, in
which case the side effects are confined to SQL.

I also think there's an ontological error in this argument. Its foundation is
that FP tries to "ignore" side effects even though they are real, but the
examples the author gives are several layers of abstraction below. C also
woefully ignores _some_ of the side effects in the silicon (e.g. if you go low
enough, calling a function with no side effects that does not even alter the
state of the program will, in fact, alter the state of the underlying silicon,
and quite substantially so), and I think it's reasonable to assume that we
can't quite move the debate into _which_ of those should be ignored or not.

 _All_ languages abstract the silicon away, and it's not only good that they
do, it's what they were built for. I honestly don't miss hardwiring relays.

~~~
w0utert
>> _There are a lot of things wrong with Java, of course, which does not mean
that they are also issue of object-oriented programming. Inheritance
(sorry...) doesn 't work both ways: the fact that a Lexus is prohibitively
expensive doesn't mean moving vehicles are prohibitively expensive._

But isn't the main point of the article that OOP just doesn't _always_ fit the
problem domain, that _sometimes_ you want to model something in a way where
forcing it into objects (nouns and verbs) only adds complexity without
benefits?

I don't think the article condemns OOP in any way except when it becomes a
religious dogma that everything needs to be an object, as it is in Java. I've
written many different types of programs in various languages, and I can only
agree that sometimes, OOP simply isn't what you are looking for. Think about
streaming data processing for example, or something reactive like a network
service. Surely some parts of the outside interface or the 'glue' between the
outside interface and the actual number crunching or request processing can be
modeled using OOP, but at the core, there's all kinds of processing on blocks
of data or asynchronous IO going on that doesn't need objects and methods, and
doesn't add to code clarity or stability in anyway (on the contrary even).

The article basically perfectly describes why I very much prefer programming
in Python or C++/Objective-C over Java: they allow me to mix and match
different programming paradigms for different problems.

~~~
chriswarbo
> I don't think the article condemns OOP in any way except when it becomes a
> religious dogma that everything needs to be an object, as it is in Java.

But Java _doesn 't_ make everything an object. The obvious one is that
'primitive types' aren't objects (int, bool, float, etc.), but also Java has
hard-wired control structures (for, while, if, try, etc.) which aren't OO
(compare to Smalltalk, for example; where "ifTrue" is a method of boolean
objects, "each" is a method of collection objects and "times" is a method of
number objects). Also its classes and methods aren't objects, like they are in
Smalltalk, Python, etc.

I would argue that that Python's first-class classes and first-class
functions/methods makes it much more 'religiously OO' than Java.

Just because all code must be in a class, doesn't mean that everything in Java
is an object. I don't know why people keep saying that.

~~~
bad_user
My favorite in Java are String instances, which are objects, but adding them
with + is not a method call, because Strings are also primitives, sort of,
hence + is in fact either eliminated (if adding two constant values) or the
code gets translated to a concatenation powered by an ad-hoc StringBuilder
instance. The JVM doesn't even pretend that a static method was invoked. It
simply pukes some bytecode.

For example there is no interface in Java that you can use to add stuff,
because from the language's point of view, adding integers is totally
different from adding strings which is also totally different from adding
BigIntegers, which is totally different from adding BigDecimals. Well, to be
pedantic, Strings addition is in fact concatenation, as Strings are in fact
Lists of Chars. I know, not fair to put them in the same bucket.

But, but, wait for it - BigDecimal and BigInteger actually do implement a
Number class. But apparently Numbers in Java's vision are not even monoids,
let alone rings (because duh, you also have multiplication). Let's not even
mention that all real numbers have natural ordering. Like seriously, how can
one get this so wrong?

Coupled with the explicit typing needed and the lack of type-classes or
anything similar, it means that you simply can't write functions that operate
on Numbers, as there is no such thing and you can't implement it by yourself.

People that bitch about Java being too OOP, missed a couple of lessons on
their way to enlightenment.

------
stevecooperorg
Reminds me of this paper;

"The Interactive Nature of Computing: Refuting the Strong Church-Turing
Thesis" \-- [http://cs.brown.edu/people/pw/strong-
cct.pdf](http://cs.brown.edu/people/pw/strong-cct.pdf)

"The theoretical nature of computing is currently based on what we call the
mathematical worldview. We discuss this worldview next, contrasting it with
the interactive worldview."

~~~
nagatoism
The paper's author should be slapped by the any CS book contains (Theorem:
IP=PSPACE)

------
joe_the_user
This is an interesting article.

It is the first critique of functional programming I've read from someone who
clearly knows their shit.

I plan to look at miniKanren more when I get the chance.

I done a fair amount of math though likely less than the author but I have a
similar impression - the things that are hardest to understand aren't
necessarily the best tool for every job, despite their beauty. And beautiful
abstraction for its sake can be a dangerous anti-pattern as much as excess
hacks and simplicity.

~~~
danieldk
_It is the first critique of functional programming I 've read from someone
who clearly knows their shit._

The critique is 'Haskell takes FP to an extreme and I show this is true
because someone tried to implement miniKanren and needed Oleg to do it'.

That is not really a strong argument.

Also note that he isn't really arguing against functional programming, but
_pure functional programming_.

 _the things that are hardest to understand aren 't necessarily the best tool
for every job, despite their beauty._

Haskell in itself is a very simple language. Most functor and monad instances
are also easy to understand or use. I agree that there is a tendency in the
Haskell community to put abstraction on abstraction, especially when the
abstraction is new. But in the end, most of the Haskell packages that became
widely-used (bytestring, text, vector) are easy to understand and use.

~~~
effn
> The critique is 'Haskell takes FP to an extreme and I show this is true
> because someone tried to implement miniKanren and needed Oleg to do it'.

>That is not really a strong argument.

It's worse than that. The linked paper is about implementing minikanren _as a
monad transformer_ , which is a lot trickier than just porting it over,
regardless of language. It's probably a lot easier in Haskell than in Scheme
though.

Furthermore, if pure FP is useless, then monad transformers are useless too.
But then the argument becomes "this useless thing is really tricky to
implement in Haskell, therefore Haskell is useless". The only reason you would
want Oleg's minikanren to be easy to implement is if you actually want pure
FP. So the argument kind of negates itself.

------
debacle
I think all this blog post really highlights is that you can get a PhD without
understanding OOP or functional programming.

------
username42
Nothing wrong with OO or pure FP. They combine very well in languages like
scala. The author complains that "in Scala, functions are just objects with a
method named apply" and complains also about "lack of first-class functions"
in java. In fact, these languages supports clean modelisation of the
algorithms using high level concepts. The target is a microprocessor that
understand low-level imperative code with side-effects. If you look only at
the first steps of the transformation, it may always look wrong. The distance
between the code and the execution may make the program more difficult to
analyse but it is a normal price for abstraction. The only thing that is wrong
is that the author is looking at high level languages with a focus on low
level semantic. The fact that "int" is not really an object in many languages
is becoming more and more an implementation detail.

------
aklein
This person is pursuing a PhD in Computer Science?

"If you look deep into them, monads make programs complicated and hard to
write, and monad transformers are just ugly hacks."

Wow. Just... wow.

~~~
drcode
Monad transformers are ugly, ugly, ugly (though not really hacks, since they
are based on sound mathematics.)

------
codygman
I think that OP mistranslates "extreme functional programming" as "we never
have side effects and compose functions".

Also what exactly is "extreme functional programming"? Only using functional
programming paradigms and abstract data types instead of OOP paradigms and
objects? Is "extreme functional programming" not taking advantage of do
notation, ST monad, etc and only programming in pure functions thereby
accomplishing nothing?

I think the author should have defined what he believed to be extreme OOP and
extreme FP before going on such a diatribe (on mostly FP and haskell in
particular, since others don't separate side effects).

------
DanWaterworth
Functional programming wouldn't be useful if side-effects didn't exist. So,
arguing that functional programming isn't useful because:

> There exists things that are not pure. Side-effects are very real.

Is nonsensical.

------
sorincos
"The lack of first-class functions is the major reason why there are so many
“design patterns” in Java. Once you have first-class functions, you will need
almost none of the design patterns."

Now this is a very bold statement. I'm dying to hear more on how you can get
rid of design patterns with first-class functions. Does it mean getting rid as
in: sharing knowledge is not needed anymore and programming becomes art as we
all head to the rapture?

~~~
tomp
FactoryFactoryFactoryClass, most of dependency injection frameworks, anonymous
classes, several different one-method interfaces, (such as event
handlers/observers), and probably more become unnecessary when you have first-
class functions.

~~~
huherto
I am currently experimenting with Spring JavaBased config (As opposed to XML
based) It seems to me that a lot of those factories are created to be able add
complex behavior in the XML configuration. I almost want to say that it is XML
injection what is causing such complexity.

~~~
tomp
No no no, I wasn't trying to say that Factory pattern in itself is useless, or
dependency injection frameworks, or similar. These are all useful things,
time-tested. However, in a language with first-class functions, all these
cease to be "obscure patterns that you need a certificate to think of and
design" and simply become "just another day of life". For example, you don't
need to create a FactoryFactoryFactory class with appropriate functions and
the whole framework around it, you simply write a function that takes the
appropriate parameters and returns the appropriate object, and pass it around.
Similarly, you don't need a complicated Dependency Injection framework, you
just pass parameters to a functions and it gives you what you want. It's that
simple. Still, occasionally some advanced IoC functionality can be useful, but
much less frequently.

To see this in action, try googling "factory pattern in Python". You will find
hardly any results.

------
lukaseder
Sign. Yet another discussion full of trolling pros and cons of FP vs. OO

Guys, listen to Simon Peyton Jones himself: "Haskell is useless". He's
discussing stuff with Erik Meijer in this video:

[http://www.youtube.com/watch?v=iSmkqocn0oQ](http://www.youtube.com/watch?v=iSmkqocn0oQ)

~~~
freyrs3
His comment was of course tongue in cheek. He wouldn't spend 25 years of his
life working on it if he thought it was useless.

------
zamalek
If we accept the author's argument; then what is the "correct" type of
language? Hybrid? A functional-OOP-CES-actor-message-passing language?

In all seriousness I do think there is definitely room for something better
than what we have today. I remember a quote saying that "compilers are build
for computers, not humans" and I'm starting to agree with that more and more.
Our minds are primitive and OOP, functional and threading is simply asking too
much of them (proof: all software has bugs). So while the author might have
called out OOP and functional in particular I think programming languages as a
whole are lacking.

------
aufreak3
I was reminded of Anton van Straaten's "koan" on closures vs. objects with
venerable master Qc Na [1] ... but I digress. This post is actually a troll
post designed to re-ignite fiery discussions about which is the superior PoV -
functional or oop - and I'm going to bite.

The only point I'm willing to give is the somewhat sane zen-like advise of
"don't fall in love with your models".

Regarding OOP, I recall Alan Kay saying something to the effect of "OOP is not
about objects. It's all about messages." which nicely points to the dualism
between the two points of view.

    
    
        > There exists things that are not objects. Functions are not objects.
    

Well, objects are any "thing" that you can talk about, toss about in your
head. Functions are certainly such "things" and count as "objects" in that
sense. If we accept that "monotonic" is an adjective, i.e. an attribute of a
noun, then the function described as "monotonic function" is an "object".

    
    
        > There exists things that are not pure. Side-effects are very real.
    

Um, how so? One notion that characterizes side-effects is irreversibility. You
cannot unlaunch a rocket, for instance and so it counts as a "side effect" of
the code "launch rocket". Despite that, when we look at the basic equations of
quantum mechanics, they are all pure unitary! I mean, not only are they
perfectly reversible, quantum "information" cannot be destroyed or even
copied. So with fundamental physics we have the opposite question - how the
hell do we get "side effects" out of this much purity at the core?

    
    
        > Also purely functional languages cause a huge cognitive cost. 
    

I call _pure BS_ on this section. "Huge cognitive cost"? For whom? Wouldn't
"structured programming" have placed huge cognitive costs to former "goto
programmers"? It is more honest to just say "I don't understand monads, so I
won't use them."

    
    
        > If you look deep into them, monads make programs complicated and hard to write
    

Again, "complicated" for whom and "hard" for whom? Is there some objective
sense in which such declarations can be made? I, for one, have benefited
greatly from learning about monads, reading monadic code and recognizing the
pattern in existing code.

    
    
        > You can write pure functions in any language, but the important thing is, you should be allowed to use side-effects too.
    

Why? Who's to say you "should" this or "should not" that?

    
    
       > Everything starts to do harm when they are pursued to the extreme.
    

I'd say the exact opposite actually. Both OOP as well as the functional
perspective here illuminate the programming world _only_ when taken to the
extreme. Until then, folks just keep arguing about what is functional and what
is oop and what isn't. Haskell and Smalltalk/Self have done this favour for us
by adopting these extreme dual perspectives.

[1] [http://people.csail.mit.edu/gregs/ll1-discuss-archive-
html/m...](http://people.csail.mit.edu/gregs/ll1-discuss-archive-
html/msg03277.html)

~~~
aufreak3
The Alan Kay reference is from his OOPSLA'97 talk [2], where he says that he's
"apologized profusely over the last 20 years for introducing the term 'object
oriented'" and suggests that the Japanese notion of "Ma" or "the unseen stuff
that goes between objects" as what is important.

(edit) [3] is a quote from a communication with Kay in 2003 -

"OOP to me means only messaging, local retention and protection and hiding of
state-process, and extreme late-binding of all things. It can be done in
Smalltalk and in LISP. There are possibly other systems in which this is
possible, but I'm not aware of them."

[2]
[https://www.youtube.com/watch?v=oKg1hTOQXoY](https://www.youtube.com/watch?v=oKg1hTOQXoY)
(around 38minutes)

[3] [http://userpage.fu-
berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...](http://userpage.fu-
berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en)

------
turingbook
It seems that the author has deleted the original article and posted a reply
to critical comments from Haskell school:
[https://yinwang0.wordpress.com/2013/11/09/oop-
fp/](https://yinwang0.wordpress.com/2013/11/09/oop-fp/)

And some content of the original article was posted to:
[https://yinwang0.wordpress.com/2013/11/16/pure-fp-and-
monads...](https://yinwang0.wordpress.com/2013/11/16/pure-fp-and-monads/)

------
nickthemagicman
Is there a blend between the two? I really like loops...

~~~
acjohnson55
Let go of your loops and learn to map, flatMap, and fold! Once I really
figured out how to use those effectively, I've written far few indexed for
loops. I tried to explain this philosophy on a recent and unheralded SO
answer: [http://stackoverflow.com/questions/19720830/is-it-safe-to-
mo...](http://stackoverflow.com/questions/19720830/is-it-safe-to-modify-an-
array-while-looping-it/19721042#19721042)

~~~
nickthemagicman
That looks sweet but I can't help but wonder: How are those implemented
internally? It seems like it would be loops?

~~~
acjohnson55
It depends on the language and library. You can implement them, or any loop
for that matter, or any computing construct furthermore, with function
application alone. This is what the lambda calculus [1] and combinatory logic
[2] are all about.

In actual languages, it depends. In languages without tail-call optimization
[3] (i.e. Python and JS), a loop is probably the most efficient way. But with
it, it's not particularly important. In a purely functional language, loops
indexed by mutable variables aren't on the table, so you have to go the
recursive route.

A basic flatmap on a list is pretty easy to define without for loops in JS
(although I would definitely recommend just using a library for all sorts of
practical concerns):

    
    
        function flatMap(list, f) {
            if (list.length) {
                return f(list[0]).concat(flatMap(list.slice(1), f));
            } else {
                return [];
            }
        }
    
        flatMap([1,2,3], function (x) { return [x, x]; });
        // -> [1, 1, 2, 2, 3, 3]
    

[1]
[http://en.wikipedia.org/wiki/Lambda_calculus](http://en.wikipedia.org/wiki/Lambda_calculus)

[2]
[http://en.wikipedia.org/wiki/Combinatory_logic#Combinatory_l...](http://en.wikipedia.org/wiki/Combinatory_logic#Combinatory_logic_in_computing)

[3]
[http://en.wikipedia.org/wiki/Tail_call](http://en.wikipedia.org/wiki/Tail_call)

------
wes-exp
Though poorly articulated, I am with the author that OOP done wrong (e.g.,
Java) is horrible. It leads to FactoryFactoryFactory and a lot of insanity!

------
anuraj
Use the tool that is apt for the job. Programming languages and paradigms are
tools. Tools are not greater than end products - period.

~~~
marshray
Part of me likes the part where he wrote "Don’t fall in love with you model".

Another part of me feels like that's saying "Don't fall in love with your
future spouse".

------
jokoon
I don't know about you, but I find those debate a little depressing. A
language will always have a certain flavour and angle to how it outputs or
executes machine code. A language will always abstract thing so it can be
better understood by a human brain.

There will always be a problem about orienting a language in a certain way,
because there are not such thing as perfect when you design something, there
are only compromises. A language orientation is a choice among many, and that
will only better fit certain cases more than other.

Just be thankful to have working languages, and if you're not, just try to
make one what either fit what you want, or try to have both OOP and functional
features. I can't understand how people can actually criticize programming
styles and language without trying to understand why such or such language is
already great.

And by the way, you can't really weigh how a language is good or not, it's
like benchmarking english or mandarin or spanish or french.

I'd just like to know how functionnal programming and OOP solve certain
similar problems, and when it's better with one or another. Because let's be
honest, programming style have nothing to do with theory, you can only judge
when you have to engineer something.

------
drharris
I thought this was going to be one of those one-word websites that said
"Nothing". There's nothing wrong with either OOP or FP, only something wrong
when people misapply them.

------
eli_gottlieb
This ignores the rise of effect systems, which take monadic effect-handling
and place it into the realm of static analysis, where it belongs.

Disciple is the future.

------
OhHeyItsE
Just [http://www.scala-lang.org/](http://www.scala-lang.org/) and everybody's
happy :)

~~~
acjohnson55
I'm putting a lot of time and effort into mastering Scala, because I think
that it's the future, paradigmatically speaking. But I think the muddled
syntax and the complexity of the language may doom it. But I think it's the
vanguard of the revolution. I was really psyched about Pyret
([http://www.pyret.org/](http://www.pyret.org/)) when I read about it here
over the weekend, and I think it hopefully represents the future of how we
program.

~~~
runT1ME
Come to #Scala and #Scalaz on Freenode IRC, it's a great learning resource.
(REPL in the chat so you can get realtime help with code).

------
hawleyal
Complete nonsense.

------
dschiptsov
This is solved long ago, without taking any extremes. In short, a language
should be mostly-functional, which means when you really need to overwrite a
value you just do it. In well-researched languages, such as Scheme you have
set!, in CLs you have setf.

All the monadic stuff (remember, that a monad is nothing but an ADT - Abstract
Data Type) is already an extreme, because one _must_ structure the code in a
certain way. However, one could write monads in Scheme, there is absolutely
nothing special about them.

I think that monad madness it is of the same nature as over-engineering
madness that plagues OOP - wasting of time and effort on construction of vast,
meaningless class hierarchies.

On the other hand, to find a balance is the most difficult task. Scala, it
seems, is close enough, but the ugliness of static typing - parametrized types
polymorphism is still here. On the other hand, it avoids mutation whenever
possible, uses persistent data structures and first class functions, which
results in a much more reasonable and predictable, and, as a consequence,
reusable and manageable code (modularity with almost no side-effects).

Yet another point is that there are literally tens of implementations of OOP
features for CLs and even Schemes, which might suggest to you that OOP is just
a set of conventions and rules - how to reference and dispatch methods -
nothing but pointers and procedures, which are the most fundamental
abstractions in CS.

The big ideas from Lisps, like everything is a reference, values have type
(tags) not variables (you don't need Nothing to be a subclass of everything,)
together with first-class functions without side-effects is that _good-enough_
set of features for a programming language.

The point is that so-called "best of the both words" was discovered long ago
in classic Lisps and it could be loosely called a _mostly-functional
language_.

~~~
quchen
You can't have monads in Scheme due to the lack of a type system. What you can
have are instances of monads, but the point of using the concept of a monad is
to abstract over it, and to have functions that work with any possible
instance.

~~~
dschiptsov
[http://karma-engineering.com/lab/wiki/Tutorial10](http://karma-
engineering.com/lab/wiki/Tutorial10)

~~~
fzltrp
Genuinely wondering: does this provide type safety?

~~~
quchen
No, that would happily evaluate "(sequence_ ((display 'a) nothing))".

------
cLeEOGPw
I think that despite all mistakes that are in the article all agree that
extreme OOP and extreme FP are almost equally bad and the balance between
those gives the best results.

