
John Carmack: Functional programming in C++ (2012) - cpeterso
http://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php
======
Arjuna
In case you missed it, John discussed his functional programming adventures in
Haskell at QuakeCon 2013... well worth a listen.

 _" So what I set out to do was take the original Wolfenstein 3D, and re-
implement it in Haskell."_

[...]

 _" I've got a few conclusions coming from it. One of them is that, there's
still the question about static vs dynamic. I know that there was a survey
just coming out recently where the majority of programmers are still really
not behind static typing. I know that there's the two orthogonal axes about
whether types are strong or weak, and whether it's static or dynamic. I come
down really pretty firmly, all my experience continues to push me towards this
way, that strong, static typing has really significant benefits. Sometimes
it's not comfortable, sometimes you have to build up a tight scaffolding to do
something that should be really easy, but there are real, strong wins to it."_

[https://www.youtube.com/watch?v=Uooh0Y9fC_M#t=4876](https://www.youtube.com/watch?v=Uooh0Y9fC_M#t=4876)

(Starts at approximately 1:21:16 in case the direct link doesn't work
correctly.)

~~~
nickbauman
I used to think that way too. I've met programmers who still don't write unit
tests and are not test driven and remain brilliant. Carmack is one of these
guys. I think the static / strong typing thing works well with them because
they never developed the practices. If you're test-driven, you're basically
building up your own, domain specific compiler as you go not having to play by
a language-specific static type systems rules. Dynamic typing make writing
code this way really easy. Static typing doesn't. In the end I want the types
of my system to work they way my system needs to. I could care less about the
type system of merely a language (as applied to my system). And types are just
one way to enforce correctness.

Lately I find with languages in the Lisp family, these other types of tools
feel much more productive, easier to reason about and flexible to me than type
systems. When I believed in static typing I felt very busy, but I was mostly
spending my time making the compiler happy, rather than the other way around.

~~~
sbergot
Except that to perform the level of checks that a compiler does with a good
type system, you would have to write a large amount of tests. Code is a
liability, and testing code is no exception.

Writing tests in static languages is still required. You just have to write a
smaller amount of them. What's more, type checking is enforced in a more
systematic way. With tests, you have to rely on people to write them. If a
type system is well designed, people will use it to model their code, and the
type checking is done automatically.

What's more, types should not be reduced to the type checking phase. Types are
a way to provide a high level model/structure. You still need this if you are
working in a medium/large project. With static types, this model have nicer
semantics, and is more useful.

~~~
nickbauman
Ok try this: Go model a square and a rectangle in your favorite statically
typed language. You will find that square extends rectangle and setting the
length on a square also sets the width. So far so good? So if I have a
collection of rectangles which contains an unknown number of squares of which
I set the width on each of them. You can't answer the question as to whether
the result is correct or not. And I have just destroyed your type system's
purpose by using polymoronism, expectoration and dispossession, the three-
legged stool of static typing OO, with a very simple and well-defined domain
subset of geometry.

Of course it's contrived but since I've been programming (which is longer than
I care to say here, because it really dates me) this is basically where I'm at
with static type systems. AS long as I've spent with them I find they're not
as useful as they should be. I haven't tried Haskell (I probably should) but
I'm getting too much done with dynamic languages, especially Lisps, to look
back right now. Too much power to look away. Tschau!

~~~
codygman
> Go model a square and a rectangle in your favorite statically typed
> language. Okay.
    
    
        data Shape = Square Int | Rectangle Int Int deriving (Show)
    

> You will find that square extends rectangle and setting the length on a
> square also sets the width. Why? I don't really see a need for square to
> extend a rectangle.

> So if I have a collection of rectangles which contains an unknown number of
> squares of which I set the width on each of them. Like this?
    
    
        > let unknowns = [(5,4),(3,2),(4,4)]
        > let toShape (x,y) = if x == y then Square x else Rectangle x y
        > map toShape unknowns
        [Rectangle 5 4,Rectangle 3 2,Square 4]
    

Tomorrow I'll see if I can make this type-safe by using dependent typing as
shown in: [0][1][2]

This was easily solvable in my staticly typed language as you can see. In
something like Idris I could have very easily encoded the toShape function the
the type signature.

0: [http://www.alfredodinapoli.com/posts/2014-10-13-fun-with-
dep...](http://www.alfredodinapoli.com/posts/2014-10-13-fun-with-dependent-
types-in-haskell.html) 1: [https://www.fpcomplete.com/user/konn/prove-your-
haskell-for-...](https://www.fpcomplete.com/user/konn/prove-your-haskell-for-
great-safety/dependent-types-in-haskell) 2:
[http://jozefg.bitbucket.org/posts/2014-08-25-dep-types-
part-...](http://jozefg.bitbucket.org/posts/2014-08-25-dep-types-part-1.html)

~~~
nickbauman
> I don't really see a need for square to extend a rectangle.

Except that a square is-a rectangle! Especially in terms of geometry. So you
should be able to use this isomorphism in a type system as a perfect
isomorphic mapping this is the entire purpose of the Liskov Substitution
Principle. But the polymorphic result doesn't work polymorphically in a way
that helps people reason about how the system works. It does things that are
"correct" from a LSP and static typing system POV, but isn't helpful.

~~~
dragonwriter
> Except that a square is-a rectangle! Especially in terms of geometry.

The thing in geometry that is called a "square" which is a special case of the
thing in geometry which is called a "rectangle" is an immutable object whose
side lengths and other features are _part of its defining identity_.

Modeling this relationship works perfectly fine in an OO language -- but
squares and rectangles of this type are immutable objects.

A _mutable_ square with operations which mutate the side lengths while
preserving squareness is _not_ a special case of a _mutable_ rectangle with
operations which mutate side lengths while preserving rectangleness without
also preserving aspect ratio.

The analytical problem here is mistakenly assuming an is-a relationship that
applies to immutable entities in geometry applies to mutable objects whose
mutation operations are defined in such a way that the is-a relationship does
not logically hold.

> So you should be able to use this isomorphism in a type system as a perfect
> isomorphic mapping this is the entire purpose of the Liskov Substitution
> Principle.

Actually, the entire purpose of the Liskov Substitution Principle is to
provide an analytical basis for excluding mistakes like subclassing a mutable
"Rectangle" class for a mutable "Square" class with operations that aren't
consistent with an is-a relationship simply because of an intuition about an
is-a relationship between squares and rectangles in geometry which doesn't
actually hold when you analyze the operations on the particular entities you
are modelling (which are outside of the geometric definitions of squares and
rectangle.) The LSP _defines_ what can and cannot be a subclass, and it rules
out the kind of mutable square to mutable rectangle relationship you have
proposed in this thread.

~~~
nickbauman
If LSP defines this why do people keep modeling things this way? More
importantly, why do all the type systems let me create models this way. They
have one job: to help me with correctness. Looks like that failed. So you see
my point.

------
pjmlp
C++14 can be a nice functional programming language, coupling algorithms,
lambdas, automatic memory management and secure data structures like
std::vector and std::string instead of bare bones C like data types.

It is even possible to do pattern matching,

[http://www.stroustrup.com/OpenPatternMatching.pdf](http://www.stroustrup.com/OpenPatternMatching.pdf)

[https://www.youtube.com/watch?v=OkDS6hmU-w8&list=PLoswmertKw...](https://www.youtube.com/watch?v=OkDS6hmU-w8&list=PLoswmertKw4d_lDpZGLXz8nXCIa4NuHyy)

So it can be a nice language when we have control over the codebase.

However, the biggest problem is being able to do so in the industry at large.
I am willing to bet that most C++ code in the wild is done in a pre-C++98
style, with developers unaware of what came afterwards.

Specially bad in those companies where getting any software upgraded is a pain
of bureaucracy.

------
walrus
Slightly off-topic: Does anyone know what happened to AltDevBlog? It's been
gone for 2.5 months now.

~~~
walrus
I dug into it a bit, and based on what I found on Twitter, the site crashed
hard and the owner hasn't gotten to recovering the data yet. (He mentioned
possibly having to pull it from Archive.org.)

~~~
rdc12
Hope it does come back was some golden posts there.

------
amelius
Here is a personal anecdote.

I recently tried to make a lambda function in C++ call itself. My first
approach didn't work, because the variables were captured by reference,
causing my program to crash (the enclosing scope had disappeared when my
recursive lambda function was called). I easily tracked down that problem. But
this generated a second problem: without using "capturing by reference", I
couldn't make the lambda function refer to itself!

Of course, I looked around on the internet, and I found [1], which actually
shows the insane amount of hacking required to make a lambda function call
itself. And in the end, this solution didn't even work for me.

So, concluding, I think we're a long way from "functional programming in C++".

[1] [http://cpptruths.blogspot.nl/2013/10/creating-recursive-
lamb...](http://cpptruths.blogspot.nl/2013/10/creating-recursive-lambdas-
and.html)

~~~
nly
Having a lambda call itself seems like self-serving functional wankery to me.
Lambdas in C++ are nothing but unnamed classes with an () operator. They're
blobs of captured values (or references), made immutable by default, that
happen to have a function associated with them. If you want to recurse, give
the damn thing a name, or rewrite the body in an iterative form.

~~~
userbinator
_unnamed classes with an () operator_

They do have a name, but unfortunately it's just a compiler-generated one
that's not known beforehand. And you would think that because the body of the
lambda is really inside an operator(), 'this' could naturally be used to refer
to the lambda itself, but alas, it doesn't work:

[http://stackoverflow.com/questions/14531993/can-lambda-
funct...](http://stackoverflow.com/questions/14531993/can-lambda-functions-be-
recursive)

This is one thing about lambdas that I think the standards folks messed up.
Having a lambda call itself might not be such a compelling use case, but it
comes from the more general fact that a lambda cannot refer to itself, even
though there isn't any reason preventing it from doing so; e.g. being able to
pass itself ('this') as a parameter to some other function can be very useful.

~~~
mjevans
You're asking for a persistent first class function; write it like one.

------
huodon
You can take a horse to the water but you cannot make him drink. (强扭的瓜不甜).

------
deng
Previous discussion:

[https://news.ycombinator.com/item?id=3896404](https://news.ycombinator.com/item?id=3896404)

------
vog
It would be interesting to hear what John Carmack has to say about functional
reactive programming, as that is meant to have it strengths especially in game
programming.

~~~
codygman
It probably hasn't been proven enough for him to deem worth of his time. I
don't say that condescendingly, but he seems to have a pretty pragmatic
approach to trying out new stuff. Unsurprising, given how busy he inevitably
is.

------
vog
Is there any trascript of that speech? Or shownotes? Or at least a link list?

