top | item 4731849

Hey, C Is a Functional Language Too

94 points| haileys | 13 years ago |spin.atomicobject.com | reply

74 comments

order
[+] fab13n|13 years ago|reply
...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.

[+] rauljara|13 years ago|reply
All programming languages and all programming styles can be similarly dismissed as encoding one Turing-complete form into another. Why pay attention to any of them?

This article is clearly someone having fun with their language. It isn't a serious claim about C being functional, something which the author states explicitly if you read to the end.

[+] fauigerzigerk|13 years ago|reply
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.

[+] meaty|13 years ago|reply
And if it was LISP doing this, people would be gushing all over it...
[+] ginko|13 years ago|reply
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.
[+] spacemanaki|13 years ago|reply
As jeremyjh already pointed out, this results in a pretty weak definition. You end up with JavaScript, Ruby, Python, and Objective-C all being lumped as "functional languages", and if you squint a little bit, you can put Java in there too (anonymous inner classes). I think C, C++ and C# could be as well, but I don't know them well enough.

So I don't think it's very productive to use a definition like this, but not because I want to be divisive, or "move the goal posts" or because I'm trying to be elitist here. It's because when a colleague asks you "what's functional programming?" I think it's much more helpful to describe the kind of programming that is encouraged in Haskell and Clojure than to just say, "well it's just map, filter, and fold in JavaScript".

[+] jrajav|13 years ago|reply
Rather than saying that higher-order functions is the defining feature of functional programming, I would say that it's an essential feature to support its object of defining programs in terms of (mathematical) function application rather than procedural state changes.
[+] markokocic|13 years ago|reply
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".

[+] zokier|13 years ago|reply
Doesn't function pointers enable passing functions around in C?
[+] michaelfeathers|13 years ago|reply
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.

[+] cmsd2|13 years ago|reply
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|13 years ago|reply
This seems like a lot of work just to avoid using the heap...
[+] xyzzy123|13 years ago|reply
It would be hilarious to provide this as an answer in a job interview to "how do you reverse a linked list?"
[+] jmilloy|13 years ago|reply
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|13 years ago|reply
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.
[+] jvranish|13 years ago|reply
I use clang with a -Wall and -Wextra, which will complain about all sorts of stuff I generally want to know about, including unused variables (I think gcc does the same?). For the rare cases where I actually want to leave a variable unused I do the above to make the warning go away.
[+] flyinglizard|13 years ago|reply
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|13 years ago|reply
> 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|13 years ago|reply
It looks like someone trying to prove Greenspun right.
[+] utopkara|13 years ago|reply
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|13 years ago|reply
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|13 years ago|reply
In my opinion, the meat of functional programming languages is that they are expression oriented. C clearly is not an expression oriented language.
[+] mellery451|13 years ago|reply
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|13 years ago|reply
... and why is it not obvious? just curious..
[+] cschramm|13 years ago|reply
No it's not. What makes a language functional is its ability to eliminate tail recursion.
[+] charliesome|13 years ago|reply
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.

[+] eru|13 years ago|reply
That's a very weird definition. Eliminating tail calls is fun, and useful. But not all that essential in, say, a lazy language.

Having first-class function values in the first place strikes me as way more important. Purity helps, too.

[+] jfb|13 years ago|reply
Tail-call elimination is a feature of the language environment, not of the language itself.