
Hey, C Is a Functional Language Too - charliesome
http://spin.atomicobject.com/2012/11/01/hey-c-is-a-functional-language-too/#.UJK4VD2nzm4.reddit
======
jrajav
This is essentially the technique used to implement the meat of Chicken
Scheme, too. [1][2][3] It's a pretty neat idea, but not a new one.

1: <http://en.wikipedia.org/wiki/Chicken_Scheme>

2: <http://wiki.call-cc.org/chicken-compilation-process>

3: The homepage is called www.call-cc.org :P

------
fab13n
...and pigs can fly, if you throw them fast enough.

This is just an encoding of a Turing-complete language into another, I don't
see what's been demonstrated here.

~~~
fauigerzigerk
I'm not sure this is even Turing complete considering the limitation he
mentions:

 _> The main limitation is that you need to know the size of the return
value._

~~~
jvranish
It's still Turing complete (though that's not saying much really). You can
always grow the stack more :P

~~~
fauigerzigerk
I don't think that solves the problem. Whatever fixed stack size you choose,
you still cannot write a program that determines the size of the lists at
runtime. A Turing complete system would have to be able to do that.

The only way I see is to allocate (almost) the entire machine memory to the
stack, create one giant array in that chunk of memory and then put all lists
in that single array. That's tantamount to reimplementing malloc on the stack.

~~~
charliesome
Any physical machine cannot be Turing complete because it has a finite amount
of RAM.

~~~
fauigerzigerk
Sure, but we're talking about whether or not this particular style of C can be
Turing complete and I'm not sure it is, even on a machine with an infinite
amout of RAM.

~~~
jsight
A machine with an infinite amount of RAM can have an infinite stack size.

~~~
fauigerzigerk
C arrays that live on the stack have to be created with a constant size (at
least before C99). It's a limitation of the language regardless of any machine
or stack size.

~~~
Johngibb
If we're going to grant that a machine can have infinite ram, surely we can
grant that a spec of C can have infinite stack allocated arrays... :)

------
ginko
I would say the aspect that defines a functional programming language is the
support of higher order functions. I.e. functions that can take functions as
arguments and more importantly can return functions as return value.

~~~
markokocic
I'm not that old but I remember that, back in the days, functional meant just
that you are able to use plain functions (without objects) and pass them
around. By that definition, C is functional language, as scheme or lisp or
javascript and many others.

I don't know why, but some years ago, "functional programmers" started to
change and twist the definition of functional language step by step, until all
those languages fell off and only Haskel remained as "functional enough".

~~~
jeremyjh
I don't see much use in a definition of "functional language" that includes
nearly every computer language. We already have a term for that.

~~~
Avshalom
well it's primary use seems to be providing a moving goal post for the
functional side during the occasional OO vs Functional skirmishes.

~~~
Evbn
That is required for parity with the OO side. Cf. Alan Kay on OO.

~~~
Avshalom
quite. _Smalltalk is OO_ and _Haskell is Functional_ are about the only
(currently) accepted facts about the definitions of OO and Functional.

------
michaelfeathers
I think that this is an interesting area. We can support just about any style
in an existing programming language, but there are often rough edges.

This reminds me of how I used to mimic OO in C years ago. At a certain point
you realize that you have to forgo certain things to help the person coming
after you avoid making mistake -- often they do not see the ramifications of
your conventions.

I see this in Ruby right now when I write in a functional style. The code is
often terse yet easy to read, but the lack of lazy evaluation makes it far
more memory consumptive than code written in a straightforward procedural
style. If you know you are making the tradeoff, it is fine. For many people,
it is too subtle.

------
chrisdew
This is the same as the design of Chicken Scheme's implementation (on top of
C).

[http://en.wikipedia.org/wiki/Chicken_(Scheme_implementation)...](http://en.wikipedia.org/wiki/Chicken_\(Scheme_implementation\)#Design)

------
szany
In fact it's purely functional!

[http://conal.net/blog/posts/the-c-language-is-purely-
functio...](http://conal.net/blog/posts/the-c-language-is-purely-functional)

------
cmsd2
From that it looks like the caller always has to allocate the right amount of
space on the stack to hold the result. What if the result size is known only
by the callee?

Denying yourself the use of the heap is also going to make closures rather
difficult. You can use this style to pass back a function pointer, but the
caller would also need to allocate space for the callee's captured variables.
Ick.

------
Nursie
This seems like a lot of work just to avoid using the heap...

------
xyzzy123
It would be hilarious to provide this as an answer in a job interview to "how
do you reverse a linked list?"

------
jmilloy
I disagree completely that this is a 'functional subset' of C. I also don't
know a lot about this stuff, so tear me up.

A functional language isn't just one that doesn't use malloc/only uses the
stack. It must actually not have state, and instead evaluate a single function
down to the result. Here, after calling make_lists, the input and the result
still both exist as state variables (immutable, yes, but that's not enough)!
At the same time, I haven't looked at code for a lisp interpreter, but I feel
safe assuming that it allocates some memory somewhere. Functional programming
doesn't have anything to do with the underlying implementation. The trick
here, if any, is that the "underlying implementation" and the code are in the
same language/program.

------
slig
Quick question: why does he do this?

    
    
        int main(int argc, char * argv[]) {
          (void)argc;
          (void)argv;
    

I've programmed C while in school, but I don't remember ever seeing this and
I'm not sure how to google it.

~~~
walrus
It stops the compiler from complaining about unused variables:

[http://stackoverflow.com/questions/8052091/void-cast-of-
argc...](http://stackoverflow.com/questions/8052091/void-cast-of-argc-and-
argv)

~~~
tmhedberg
Why would you do this instead of declaring it as `int main(void)`?

------
flyinglizard
At some point the stack is going to grow which will cause allocation at the OS
level. And if we're discussing small embedded systems with fixed stacks, this
code is entirely unsafe (non deterministic stack usage may cause stack
overruns).

In embedded systems (non-MMU ones) you generally want to avoid repeated
dynamic runtime allocation to prevent memory fragmentation.

It's a cute example, but I can't see any scenario where its better or safer
than heap use.

~~~
jvanenk
> It's a cute example, but I can't see any scenario where its better or safer
> than heap use.

The author does explicitly point this out: "While I find this style strangely
addictive, I don’t think I would advocate its general use."

------
agumonkey
It looks like someone trying to prove Greenspun right.

------
utopkara
Ditto on the addictiveness of continuation-passing style.

However, don't try it when coding with peers who are not used to it; you can
be burnt at the stake. Because, even though it makes the code easier to read,
to the untrained eye it is just cryptic.

------
ibotty
money quote (at the end of the article):

"So my title is misleading. I don’t think C is a functional language. But it’s
an awful lot of fun (and sometimes very useful) to use C’s functional subset."

------
vu3rdd
In my opinion, the meat of functional programming languages is that they are
expression oriented. C clearly is not an expression oriented language.

------
mellery451
it might have also been worthwhile to mention that the stack array
declaration:

    
    
       int32_t result[my_array_size];
    

relies on C99 support, which is not necessarily ubiquitous (especially in
embedded device work). At the very least, many compilers make you explicitly
enable C99 support.

------
georgeg
... and why is it not obvious? just curious..

------
Evbn
On another satirical but deeply intellectually serious note:

[http://conal.net/blog/posts/the-c-language-is-purely-
functio...](http://conal.net/blog/posts/the-c-language-is-purely-functional)

By Conal Elliot.

------
cschramm
No it's not. What makes a language functional is its ability to eliminate tail
recursion.

~~~
charliesome
GCC can eliminate tail recursion, so does that make C functional?

I don't think the author is seriously of the belief that C is a functional
language. This is just a fun little example of writing C in a functional
style.

~~~
Jach
GCC can even eliminate non-tail recursion, such as with this piece of black
magic:

    
    
        int factorial(int x) {
           if (x > 1) return x * factorial(x-1);
           else return 1;
        }
    

will be optimized by GCC to

    
    
        int factorial(int x) {
           int result = 1;
           while (x > 1) result *= x--;
           return result;
        }
    

(<http://ridiculousfish.com/blog/posts/will-it-optimize.html>)

