Functional programming in C (2013)
lucabolognese.wordpress.com
lucabolognese.wordpress.com
While these restrictions may seem silly to the HN crowd, it leads to an interesting way of thinking about solving problems.
[0] https://www.student.cs.uwaterloo.ca/~cs136/handouts/03-funct...
Is indeed a bit strange. I guess I can see the reasoning, though.
"const by default" doesn't seem all that unreasonable to me - isn't that one of the major driving forces we're seeing in "new" languages - that based on years of experience, "accidental" mutability should be avoided -- mutability should not be the default?
How does this subsetting of C affect the error messages the students are (most) likely to see? Does -Wall typically catch treating a const as mutable? (I assume so, I'm just curious about this, as I'll soon be teaching a beginning programming course - and a sub-set of C might be an interesting option).
It's linkable with C. It has first-class support for discriminated unions. Very powerful automatic cleanup. Library of minimal-overhead common data structures. Plus immutability, and a few more things heavily inspired by functional languages.
So instead of a bit odd, not-quite-portable C macros I wholeheartedly recommend using a bit odd, not-quite-portable Rust instead.
#ifdef __GNUC__
value = c->kind == Volvo ? ({
struct Volvo* it = &c->Volvo;
itoa(it->x, temp, 10);
})
: c->kind == Ferrari ? (void)c->Ferrari.model, c->Ferrari.brand
: c->kind == Fiat ? c->Fiat.model
: union_fail("Not a valid car type");
testCar(c, value);
#endif // __GNUC__
}Such bullshit.
Alas, the greater GNOME attitudes that began to copy the worst aspects of Windows after the fateful (and correct) Sun Microsystems of user experience study in the late 90s of GNOME 1.x [0], which came back with "You literally have five different clocks, including one named 'Another Clock' [1], are asking people to identify video cards by chipset, and have odd settings that are explained solely by acronyms. Get your house in order." to then mean "No options at all!", and the bad copying of the worst ideas of windows to the bad copies of the worst ideas of Apple (e.g. undiscoverable keypresses and file choosers without directory path inputs) turned me off to the whole mess.
[0] https://web.archive.org/web/20010725052737/http://developer.... [1] http://www.linuxselfhelp.com/gnome/users-guide/clock-applets...
The problem with both is that you still have to write a lot of boilerplate by hand. Of the Xt Intrinsics I know that the things you could do with it were pretty advanced for their time, just too much annoying work.
What the Gtk+ people should have done is design some nice notation for objects and generate the Xt Intrinsics object boilerplate from that. Or in fact that should have been done soon after creating Xt.
`point_t` instead of `struct point`, `color_t` instead of `enum color` or worse, `pint` instead of `int *` is stinky because it hides the actual operations which are only applicable to a struct, an enum, or a pointer, respectively.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2...
I'll postfix this by saying I actually don't consider the code snippet as ugly but that's because I like C. Most people consider C ugly because they use stuff like Python or C++ which hides some details. Macros can hide details too, they are just difficult to use. Therefore, for most people C will always be "ugly", but then again, beauty is in the eye of the beholder.
The blog mentioned on the Github page is down but the relevant URLs can be accessed from the wayback machine at [1] and [2].
GCC also supports nested functions [3] (as a GNU C extension).
Unrelated, but [4] specifies a pure C implementation of Go channels and libmill [5] is a library that introduces Go-style concurrency to C.
[0] https://github.com/cioc/functionalC
[1] https://web.archive.org/web/20160406001106/http://blog.charl...
[2] https://web.archive.org/web/20160304120857/http://blog.charl...
[3] http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
http://www.gamasutra.com/view/news/169296/Indepth_Functional...
Some really choice quotes in there.
With some fancier variable macros + C11, you can even make closures in C viable [2].
[1] https://github.com/naasking/libsum
[2] Incomplete, but both curried and uncurried closures are possible: https://github.com/naasking/cclosures
$ chgrp sane_c_devs /usr/bin/gcc
$ chmod 0770 /usr/bin/gcc
Of course, the following scenario is not impossible ;) $ getent group sane_c_devs | cut -d: -f4 | tr , "\n" | wc -l
0having had to deal with the grief that was a late-90s attempt at OO C.... stay away from this.
Tooling is designed for idioms of the language. Attempting to be 'clever' means you have to throw away all the benefits of that tooling as well as reducing your maintainability and confusing the optimiser.
I'm not saying all C programmers should use OO techniques, and I'm not saying all OO programmers should reach for C, but I don't think blanket statements like "OO C is a bad idea" and "stay away from [OO C]" are useful without context (and with context they are almost meaningless).
What I'm referring to is the manual creation of virtual pointer tables and dereferencing everything through it. This completely defeats the optimiser as it can't see thru the pointers. The case I'm referring to was a complete WTF in hindsight.
virtual pointer tables are an age-old 'C' mechanism of providing runtime configuration for drivers and such like.
the WTF project, took that idea and had virtual pointers for everything methods, data, superclasses, etc.
Every line consisted of something like the following:
obj->vptr->methodA(obj, objB->vptr->methodB());
it very rapidly becomes a readability and maintainability nightmare.
the WTF project would have '->vptr' and worse '->super->vptr->method(), maybe 20 or 30 times per function.
every call in the codebase or data reference would be via a '->vptr'.
That really makes a difference.... its unreadable. literally.
I think that's why I'm not following you. You've dismissed OO in C in its entirety, and advised others to do the same, based on your experience in one project which misused/overused the feature.
The level to which it is used in Linux is effectively idiomatic.
The project I'm referring to used the technique properly. Its just a bad technique.
So you can see how I'm confused about what your opinion really is, I hope.
https://gist.github.com/machuidel/d7cc099ddc4970c6ddf4
By adding more abstractions it should even be possible to support semigroups, monoids etc.
Of course this was just for fun.
It's fun to get some of the functional flavor, while still being very near the bare pointers.
Using preprocessor macros to try to create new language constructs is pretty much always Bad News(tm). Almost as bad as using C++ operator overloading to completely change the semantics of an operator. (Bitwise or? Yeah, that's some sort of weirdo automatic function nesting thing now, but only here, and 6 lines down.)
Dina Byrnes: I had no idea you could milk a cat!
Greg Focker: Oh, you can milk just about anything with nipples.
Jack Byrnes: [He reacts] I have nipples, Greg, could you milk me?
Not at all. Please go ahead and post it.
> your mom
>There is one irritating thing about C as a viable programming language.
Given its history, I don't see where this guy comes from that he can declare whether C is a viable programming language or not. Especially when his real complaint is not about C at all.
>Microsoft’s compiler support is not good.
While some may complain that I'm making a minor quibble, my point is, when you make statements like this, your credibility falls a notch or twelve and I have to look at the rest of the article with suspicion.
For example, C99 designated initialisers aren't in C++ at all, which is a shame as they're fantastically useful:
struct foo {
int i;
double j;
};
struct foo f = { .j=9.1, i=4 };
See http://stackoverflow.com/questions/18731707/why-does-c11-not....Likewise MSVC will support C11 libraries when they get around to be fully C++17 compliant.
For any newer C standard the official Microsoft position is to use clang with the Visual C++ backend, called C2 which Microsoft is turning into a backend to be shared between clang, Visual C++ and .NET Native.