
An Apology of Sorts: Functional Languages Are (Still) Overrated - fogus
http://www.benrady.com/2012/09/functional-languages-are-still-overrated.html
======
tikhonj
Functional languages may be overrated, but not nearly as overrated as
imperative languages (especially Python and Java). At the very least, avoiding
Haskell is--unfortunately--quite easy; avoiding Java or Python in most places
is nigh impossible.

The past post he references can be summarized by its last sentence: "I
seriously don't get it." It spends quite a bit of effort telling us very
little about functional languages but quite a bit about the author. And, as
usual, he mistakes difficultly for complexity--just because something is new
and mind-bending does not mean it is _complex_ ; it could just be a little
tricky to pick up. (This is where Rich Hickey's "Simple Made Easy" talk really
shines.)

And, of course, in the current post he misrepresents the main case for
functional programming. Which is--quite critically--not concurrency _or_
parallelism! These are, in fact, just nice benefits. The main point is using a
higher level of abstraction, reducing coupling, simplifying code, writing
_less_ code to do _more_ and making it easy to reason about and verify.

If all you care about is concurrency, Haskell is probably not your best bet.
But if you care about writing maintainable, reusable and more general code
more quickly and without sacrificing too much performance, it is. I would--
without thinking twice--use Haskell to write programs in a completely single-
threaded world. Haskell may also be good at dealing with concurrent nonsense,
but this is really just a symptom of a deeper cause: Haskell is good at
dealing with complexity.

If that doesn't convince you, Haskell also comes with a ton of shiny toys like
QuickCheck and Parsec. It might not have the _biggest_ collection of
libraries, but it probably does have one of the most _innovative_.

~~~
soup10
Programming languages can strive to be either tools or toys.

Programming languages that strive to be tools focus on high quality standard
libraries, speed, good debugging facilities, being easy to learn, ability to
handle large projects, and hardware support among other things.

Toy languages strive to be innovative and explore new depths of computer
science. Which is all well and good, but it's pretty annoying when people
compare them with 'real' programming languages.

~~~
derleth
> high quality standard libraries, speed, good debugging facilities, being
> easy to learn, ability to handle large projects, and hardware support among
> other things.

Hm. C has three, at most four of those desiderata. It lacks good debugging
facilities, especially compared to what a _real_ (Smalltalk or Lisp, for
example) debugger can do, it is about as easy to learn as driving a car with
manual transmission, manual steering, and inadequate brakes, and it is so
lacking in support for programming in the large that people were willing to
put up with 1990s-era C++.

So is C a toy?

~~~
dchichkov
Right. And also this 'real' debugger would not be predictable, would crash,
wouldn't work with my favorite environment, would be a hell to install, etc...
No, thank you very much, good old GDB is fine with me.

~~~
derleth
None of those things are or were problems with Smalltalk and Lisp
environments. You might as well rattle off the potential downsides of using a
compiler instead of writing machine code by hand.

------
bunderbunder
There is one language that stands way out at the forefront when it comes to
working on enabling B grade programmers to write scalable, concurrent systems:
C#.

I think a big part of its success is that it avoids the hype machine. It isn't
a disruptive language that changes the way we do things. It can't be, or
management would be justifiably wary of it. Instead, it's a language that
started out as a very close clone of Java, and since then its designers have
been rapidly iterating to the point that it's now a (mostly, some would say)
functional language that's solidly embedded in the enterprise space.

It's somewhat disappointing that it's still missing algebraic data types and
pattern matching. But considering I've got most of what I want without ever
having had to pitch switching languages to an employer, I'm really not in a
position to complain too much.

~~~
debacle
While I don't disagree that C# is good, I don't see how you could say that
Java is in any way behind. At least in concurrency, I would argue that it's
somewhat ahead. Threading in Java was more intuitive to me than threading in
C#.

~~~
usea
In the past few years C# updates and new .net libraries have had a sort of
concurrency and parallelism focus.

The Task Parallel Library (TPL)[1] is basically like goroutines in Go. They're
a concurrency construct, for executing code that gets multiplexed to threads
via the thread pool by default. Absurdly useful and very easy to use. This
contains stuff like Task, Parallel.ForEach, .ContinueWith() etc.

The TPL Dataflow[2] stuff added just recently is data pipelining. Completely
thread-safe communication of data, with the ability to construct a complex
data pipeline that your data gets pushed through. Similar to channels in Go.

Also added recently are the async and await keywords[3] in C# and VB.NET.
These are compiler features that allow you to write asynchronous code exactly
the same way as you would write synchronous code. Basically a replacement for
the IAsyncResult + BeginFoo/EndFoo pattern, it allows you to write simple and
readable asynchronous code. Not necessarily multi-threaded as it can be used
with single-threaded code, but it allows the stuff that interacts with your
multi-threaded code to not bend over backwards for it.

[1] <http://msdn.microsoft.com/en-us/library/dd460717.aspx>

[2] <http://msdn.microsoft.com/en-us/devlabs/gg585582.aspx>

[3] <http://msdn.microsoft.com/en-us/library/hh191443.aspx>

~~~
upthedale
Don't forget Rx [1]

It enhances support for the IObservable/IObserver interfaces, the duals of
IEnumerable/IEnumerator, allowing Linq manipulation of asynchronous events.

As others have discussed or at least alluded to, C# certainly started out on a
par with Java, but has grown into a different beast altogether, if one makes
use of all the new developments mentioned.

These days my C# code is very un-Java-like, and far more Functional.

[1] <http://msdn.microsoft.com/en-us/data/gg577609.aspx>

------
jballanc
I've recently been using Clojure more and more, including introducing it for a
few nascent projects at work. I haven't been this excited about a new language
since Ruby in 2005.

Plenty has been written on its technical merits, but there is one aspect of
Clojure that I don't think enough people pay attention to: the community!
4Clojure is just one example. The #clojure IRC channel is another. The Clojure
community today feels like the Ruby community did back in 2005: hackers having
fun and getting work done at the same time.

You owe it to yourself to give it a chance...

~~~
evilduck
I'm pretty much totally ignorant about Clojure in practice. One part I love
about Ruby is being able to drop into an irb/pry session nearly instantly or
run the Rails console and test out code and ideas interactively and being able
to quickly restart the dev server if configs change. JRuby has always been
appealing to me but it's kind of annoying to use for development due to the
JVM startup time. I used to do Java development full time and had the same
annoyance with needing the compilation/restart step to see changes.

Does Clojure address this problem or are there workarounds (like Guard/Spork
for testing in Rails)? Is there anything fundamentally different from JRuby
that would alleviate the slow restarts, or am I simply thinking about the
problem wrong?

~~~
jballanc
The Clojure community just recently put its full weight behind nREPL. You can
run nREPL from Leiningen outside of a project directory, much like IRB. To be
honest, I've never noticed the JVM startup time...

But there is another way! Clojure inherits the concepts of SLIME/SWANK from
the world of LISP. Essentially, since functions (not objects) are the top-
level constructs in Clojure, you can redefine functions at any time while your
program is running, and everything will "magically" start using the new
definition.

So, the typical way one develops in Clojure is to start a SWANK or nREPL
server, then load their program files into this server. At that point, you can
run any single function or if you're writing a web app, for example, you can
run the function that starts the web server, hit a URL, edit a function, re-
evaluate, reload the web site and immediately see the results.

ClojureScript One is one example of how this can be taken advantage of. You
can see a demo of it here: <http://vimeo.com/35153207>

~~~
habitue
"Essentially, since functions (not objects) are the top-level constructs in
Clojure, you can redefine functions at any time while your program is running,
and everything will "magically" start using the new definition. "

This isn't exactly correct. It's not because clojure has first class functions
that you get this behavior, but because clojure has late binding:
<http://en.wikipedia.org/wiki/Late_binding>

~~~
jballanc
True, but Ruby also has late binding. Ruby also has open classes, so you could
(in theory) do something very close to SLIME with Ruby.

The problem is, Ruby also has singleton classes and singleton methods, so
there's no guarantee that a change made in code and evaluated in the runtime
will have the desired effect. Actually, Clojure has a similar problem with
defonce, but in practice I've found that Clojure works much better with the
SLIME development model than Ruby does.

~~~
banister
Just curious but why does singleton classes/singleton methods in Ruby make it
"so there's no guarantee that a change made in code and evaluated in the
runtime will have the desired effect" ?

~~~
jballanc
Well, a trivial example:

    
    
        class Foo
          def bar
            puts "Hello from Foo"
          end
        end
        
        a = Foo.new
        def a.bar
          puts "Hello from a special Foo"
        end
    

Now, even if you change the definition of "bar" in Foo's class definition, "a"
will still have it's own version. This might not seem like a big deal, but as
you do more metaprogramming with Ruby, more examples like this pop up.

------
T_S_
I have been using Haskell seriously for about two years now and humorously for
a bit longer. For some reason I bought the old sales pitch some time ago. Now
that I have a clue about the language I would like to rewrite the sales pitch
for anyone considering a move.

Here's what happens in the middle of a big Haskell project.

1) Take some existing code.

2) Refactor (Add a feature, change a record element, etc.)

3) Run ghc, then fix all the errors it reports. Repeat this step as needed.

4) Done.

What would be different in python? For one, no compile errors means very
little. How many test cases would you need? How would you find all the places
the code must change?

Lesson: A tough, smart compiler can be the programmer's best friend.

Meta-lesson: There is little need to discuss laziness, purity or static typing
to "sell" Haskell. They are enablers of ghc. What you need is a big,
complicated code base and an urgent need to make changes to it. You won't have
that until you get your feet wet.

Is Haskell perfect? No, but I'll save that for an OP that is overhyping the
language.

------
dons
Remarkably content-free.

------
pcote
The merits of functional programming techniques are a lot more interesting
than the languages that implement them, "pure" or not. Closures, first class
functions, and list comprehensions are interesting topics of discussion. Java
vs. Haskell not-so-much.

~~~
ky3
_Java vs. Haskell not-so-much._

But it's mostly in such comparisons that "closures" and "first-class
functions" are brought up.

If you check out /r/haskell you'd be hard pressed to find those terms.

I hardly ever think of closures qua closures; they are a language
implementation detail that's at a level barely above assembly.

------
SeanDav
I by no means want to start any kind of religious war but I feel that Scala
has kind of eclipsed Clojure. I tend to notice more Scala skills required in
real life projects than Clojure.

This is just my opinion as someone that knows neither Scala nor Clojure and
without any axe to grind in this debate.

~~~
dagw
To me it seems more that Scala and Clojure appeal to two slightly different
groups.

Scala is very appealing to people looking for a "better Java". A Java
programmer can get up and running with Scala very quickly simply by treating
as Java with some neat and powerful syntactic sugar, and then slowly segue
into the more powerful features Scala offers as and when he needs them.

Clojure on the other hand basically requires throwing out everything you know
(assuming you're not coming from a LISP background) and starting from scratch.
In exchange you end up with a very powerful and new way of approaching
programming, one which is very appealing to many people and very effective for
handling certain problems.

So as such it makes sense that Scala is more visible. If I had a large Java
shop and wanted to try using some functional programming in certain projects,
then Scala would be a no brainer.

------
debacle
Functional languages historically suffer from weak libraries. Languages built
on the JVM can side-skirt that issue quite a bit.

------
marawuti
This has been a thoroughly fascinating read. The attitudes towards development
are echos from the late '70s and the '80s. The wheel of incarnation is still
turning guys & gals.

Since the economics of systems have not changed much (70% of the cost of a
system is in maintenance) I find it humorous that nobody has mentioned making
code clear for the poor maintenance (enhancements, refactoring) schmuck.
Everyone including the hoodwinked managers are focusing on the "window of
opportunity" a.k.a lost opportunity cost of getting the project done - to
market. This is as wrong headed now as it was in the '80s.

Unless you are writing one-off systems that have a real world, crucial
deadline - think new scud detection techniques during the 1st gulf war [done
in Lisp BTW] - just focus on making systems that can first and foremost be
comprehended quickly by someone else. You're working in a team. Right? All the
rest of the hyper-fast development hoopla is self aggrandizing and for the
most part a waste.

I must admit though that the reminiscences of the days of "feeling like an
artist" contained in this thread bring back heady memories. I hear the egos of
me and my prior associates sprinkled throughout this thread.

Bon chance.

------
joe_the_user
Well,

What I would say about Functional Languages isn't that they're over-rated but
they are mis-rated if they are described as means of replacing the abomination
that is Object Oriented Programing (which I use every day).

I would free acknowledge that functional programming constructs are powerful
methods to concisely specify complex, _well-behaved_ systems. I use arrays of
function pointers and similar things when I want to create such a subsystem in
a c++ program I'm working on (obviously not using full fp but it still give
power-galore).

The thing that FP isn't is means to tie two huge, horrible systems together
(or accomplish similar tasks). And while fp might indeed be used to create a
number of elegant systems, if fp is unable to beat back the forest of
horrible, inelegant systems around us, it isn't going to replace OO and it
isn't going to get wide adoption. Because OO may be awful but has the quality
that if used judiciously, it can made ugly stuff somewhat less ugly.

~~~
tmhedberg
I'm not sure what you mean by "FP isn't meant to tie two huge, horrible
systems together". Is any language or programming paradigm really designed
with that usage in mind?

But assuming that that is in fact the case, I wonder whether it would still be
the case if we lived in a bizarro world in which FP had dominated and OOP was
seen in the mainstream as an impractical oddity. I suspect that, to the extent
that functional languages do not make for good "glue code", that is primarily
due to the impedance mismatch between FP and the largely object-oriented
systems that need tying together, rather than because of some inherent
limitation of functional programming itself. If those large systems were
constructed in a functional style, would functional glue be more effective?

~~~
tesseractive
OO code can work as reasonably effective good glue code for even older pre-OO
procedural code, or even produce usable wrappers for big messy globs of
assembly, should you have the misfortune to own that sort of mess.

So I would say that your bizarro world would need to presuppose that
functional code had dominated from the first instead of any _imperative_ code,
which may have been what you meant.

However, my suspicion is that imperative code, at it's most basic, is the
natural form for the first computer code to take, given development of simple,
early processors. My intuition could be wrong on this point, of course.

In general, though, if you have particular operations in an imperative program
that are more useful to reason about using a functional methodology, it's easy
to use OO code as glue code wrapped around it (in C#, F#, Scala, etc.). By
contrast, adding bits of imperative code inside a functional program requires
careful thought and planning to keep from breaking the rest of the program
through unexpected side effects.

So my suspicion is that OO is ultimately a better "glue paradigm" than FP. And
why I suspect that ultimately, object-functional languages are likely to
succeed more broadly in the real world than pure functional languages.

------
zem
it always surprises me when erlang is lumped in with the other functional
languages. i know it technically qualifies as one, but if i had to round up
the "mainstream" fp languages, i'd put ocaml, haskell, scala and clojure in
one group, and erlang off to one side by itself.

~~~
ludicast
Agreed, Erlang is a total weirdo.

As a language is "bad weird", but as a platform is "good weird". Projects like
Elixir are way exciting for this reason.

~~~
zem
apart from the string handling, i actually liked erlang as a language.
mailboxes and destructuring pattern matching are a very pleasant way to
organise code.

------
nirvana
I look forward to the day when Hacker News moves beyond these "my language is
better than yours" articles written by third rate programmers.

In his first paragraph it makes it clear to me that he didn't understand the
nature of any of the languages he originally discarded, and he discarded them
_because_ he didn't understand them in sort of a "its too hard or my brain,
therefore they suck!"

Which sets a really poor stage to then hear that Clojure is the second coming.

I'm neutral on clojure- but in my experience, every time I learn a new
language, for awhile it feels like the second coming, because if its a good
language it has a reason for being, and in the scope of that reason for being,
it really is the second coming.

The problem-- and what makes this guy a third rate programer-- is the latching
onto that language and it becoming your blub language.

He decries FP as a fad and offers instead, a language specific fad.

Seriously, dude? When you step up to the level where language is less
important, and it constrains your thinking less, then you'll step up to the
next level of programming ability.

